github.com/grafviktor/keep-my-secret@v0.9.10-0.20230908165355-19f35cce90e5/website/src/api.js (about) 1 import axios from 'axios' 2 import get from 'lodash/get' 3 import isNil from 'lodash/isNil' 4 import reduce from 'lodash/reduce' 5 6 const BASE_URL = 'https://localhost:8080' 7 const httpRequest = axios.create({ 8 baseURL : BASE_URL, 9 // we handle all responses independently of their HTTP status 10 validateStatus : () => true, 11 }) 12 13 const checkApiError = (response) => { 14 const status = get(response, 'data.status') 15 16 if (response.headers['content-type'] === 'application/json' && status !== 'success') { 17 const message = get(response, 'data.message', 'Unknown error') 18 19 throw Error(message) 20 } else if (response.status >= 400) { 21 throw Error(`status ${response.status}`, response.message) 22 } 23 24 return response 25 } 26 27 const getVersion = () => httpRequest.get('/api/v1/version') 28 29 const register = (username, password) => httpRequest.post( 30 '/api/v1/user/register', 31 {username, password}, 32 {withCredentials: true}, 33 ) 34 35 const login = (username, password) => httpRequest.post( 36 '/api/v1/user/login', 37 {username, password}, 38 {withCredentials: true}, 39 ) 40 41 const logout = () => httpRequest.post('/api/v1/user/logout') 42 43 const refreshToken = () => httpRequest.get( 44 '/api/v1/user/token-refresh', 45 {withCredentials: true}, 46 ) 47 const createSecretWithFile = async (accessToken, payload) => { 48 const {file, ...otherAttributes} = payload 49 const formData = new FormData() 50 51 formData.append('data', JSON.stringify({ // Add JSON data 52 ...otherAttributes, 53 file_name: file.name, 54 })) 55 formData.append('file', file, file.name) // Add the file 56 57 return httpRequest.post( 58 '/api/v1/secrets', 59 formData, 60 {headers: { 61 Authorization : `Bearer ${accessToken}`, 62 'Content-Type' : 'multipart/form-data', 63 }}, 64 ) 65 } 66 67 const createSecret = async (accessToken, payload) => { 68 if (!isNil(payload.file)) { 69 return createSecretWithFile(accessToken, payload) 70 } 71 72 return httpRequest.post( 73 '/api/v1/secrets', 74 payload, 75 {headers: { 76 Authorization: `Bearer ${accessToken}`, 77 }}, 78 ) 79 } 80 81 const updateSecret = (accessToken, id, payload) => httpRequest.put( 82 `/api/v1/secrets/${id}`, 83 payload, 84 {headers: {Authorization: `Bearer ${accessToken}`}}, 85 ) 86 87 const deleteSecret = (accessToken, id) => httpRequest.delete( 88 `/api/v1/secrets/${id}`, 89 {headers: {Authorization: `Bearer ${accessToken}`}}, 90 ) 91 92 const getSecretFile = async (accessToken, id) => httpRequest.get( 93 `/api/v1/secrets/file/${id}`, 94 { 95 // By default responseType is 'json'. If we're requesting binary data(like a file) 96 // we receive malformed document, which content is different is different from 97 // actual 'Content-Length' header value 98 responseType : 'arraybuffer', 99 headers : {Authorization: `Bearer ${accessToken}`}, 100 }, 101 ) 102 103 const fetchSecrets = (accessToken) => httpRequest.get( 104 '/api/v1/secrets', 105 {headers: {Authorization: `Bearer ${accessToken}`}}, 106 ) 107 108 const api = (context) => reduce({ 109 // cannot use map[fn1, fn2, ...] because webpack removes function names (fn.name) from 110 // prod build don't have time to make a proper setup for WebPack terser plugin 111 login, 112 logout, 113 register, 114 getVersion, 115 refreshToken, 116 createSecret, 117 deleteSecret, 118 updateSecret, 119 fetchSecrets, 120 getSecretFile, 121 }, (acc, fn, name) => ({ 122 ...acc, 123 [name]: async (...args) => { 124 context.setAppBusy(true) 125 const response = await fn(...args) 126 context.setAppBusy(false) 127 128 return checkApiError(response) 129 }, 130 }), {}) 131 132 export default api