|
|
// authentication.ts
// Copyright (C) 2020 Dwayne Harris
// This program 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.
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
import { Action } from 'redux'
import { apiFetch } from '../api' import { setEntities } from '../actions/entities' import { startRequest, finishRequest } from '../actions/requests' import { normalize } from '../utils/normalization'
import { LOCAL_STORAGE_ACCESS_TOKEN_KEY, LOCAL_STORAGE_REFRESH_TOKEN_KEY, LOCAL_STORAGE_ACCESS_TOKEN_EXPIRES_AT_KEY, } from '../constants'
import { AppThunkAction, Entity, RequestKey, EntityType, Settings } from '../types'
export interface SetCheckedAction extends Action { type: 'AUTHENTICATION_SET_CHECKED' }
export interface SetAuthenticatedAction extends Action { type: 'AUTHENTICATION_SET_AUTHENTICATED' payload: boolean }
export interface SetUserAction extends Action { type: 'AUTHENTICATION_SET_USER' payload: string }
export interface UnauthenticateAction extends Action { type: 'AUTHENTICATION_UNAUTHENTICATE' }
export type AuthenticationActions = SetCheckedAction | SetAuthenticatedAction | SetUserAction | UnauthenticateAction
export const setChecked = (): SetCheckedAction => ({ type: 'AUTHENTICATION_SET_CHECKED', })
export const setAuthenticated = (authenticated: boolean): SetAuthenticatedAction => ({ type: 'AUTHENTICATION_SET_AUTHENTICATED', payload: authenticated, })
export const setUser = (userId: string): SetUserAction => ({ type: 'AUTHENTICATION_SET_USER', payload: userId, })
export const unauthenticate = (): UnauthenticateAction => ({ type: 'AUTHENTICATION_UNAUTHENTICATE', })
export const fetchSelf = (): AppThunkAction => async dispatch => { dispatch(startRequest(RequestKey.FetchSelf))
try { const self = await apiFetch<Entity>({ path: '/v1/self', })
const result = normalize([self], EntityType.User)
dispatch(setEntities(result.entities)) dispatch(setUser(self.id)) dispatch(setAuthenticated(true))
dispatch(finishRequest(RequestKey.FetchSelf, true)) } catch (err) { dispatch(setAuthenticated(false)) dispatch(finishRequest(RequestKey.FetchSelf, false)) throw err } }
interface AuthenticateResponse { id: string access: string refresh: string expires: number }
export const authenticate = (name: string, password: string): AppThunkAction<string> => async dispatch => { dispatch(startRequest(RequestKey.Authenticate))
try { const response = await apiFetch<AuthenticateResponse>({ path: '/v1/authenticate', method: 'post', body: { id: name, password, }, })
localStorage.setItem(LOCAL_STORAGE_ACCESS_TOKEN_KEY, response.access) localStorage.setItem(LOCAL_STORAGE_REFRESH_TOKEN_KEY, response.refresh) if (response.expires) localStorage.setItem(LOCAL_STORAGE_ACCESS_TOKEN_EXPIRES_AT_KEY, response.expires.toString())
dispatch(finishRequest(RequestKey.Authenticate, true)) await dispatch(fetchSelf()) return response.id } catch (err) { dispatch(finishRequest(RequestKey.Authenticate, false)) throw err } }
interface UpdateSelfOptions { name: string about: string requiresApproval: boolean privacy: string imageUrl: string coverImageUrl: string theme: string settings: Settings }
export const updateSelf = (options: UpdateSelfOptions): AppThunkAction => async dispatch => { const { name, about, requiresApproval, privacy, imageUrl, coverImageUrl, theme, settings } = options dispatch(startRequest(RequestKey.UpdateSelf))
try { const self = await apiFetch<Entity>({ path: '/v1/self', method: 'put', body: { name, about, requiresApproval, privacy, imageUrl, coverImageUrl, theme, settings, }, })
const result = normalize([self], EntityType.User)
dispatch(setEntities(result.entities)) dispatch(setUser(self.id)) dispatch(setAuthenticated(true))
dispatch(finishRequest(RequestKey.UpdateSelf, true)) } catch (err) { dispatch(finishRequest(RequestKey.UpdateSelf, false)) throw err } }
|