lbrysync demo initial - register / auth boilerplate

This commit is contained in:
zeppi 2022-07-12 11:43:49 -04:00
parent 16fe53c47d
commit ecfbaea8b1
9 changed files with 209 additions and 1 deletions

View file

@ -13,6 +13,7 @@ const config = {
LBRY_API_URL: process.env.LBRY_API_URL, //api.lbry.com',
LBRY_WEB_STREAMING_API: process.env.LBRY_WEB_STREAMING_API, //player.odysee.com
LBRY_WEB_BUFFER_API: process.env.LBRY_WEB_BUFFER_API,
LBRYSYNC_API: process.env.LBRYSYNC_API,
SEARCH_SERVER_API: process.env.SEARCH_SERVER_API,
CLOUD_CONNECT_SITE_NAME: process.env.CLOUD_CONNECT_SITE_NAME,
COMMENT_SERVER_API: process.env.COMMENT_SERVER_API,

View file

@ -7,6 +7,7 @@ import { selectGetSyncErrorMessage } from 'redux/selectors/sync';
import { selectHasNavigated } from 'redux/selectors/app';
import { selectTotalBalance, selectBalance } from 'redux/selectors/wallet';
import { selectEmailToVerify, selectUser } from 'redux/selectors/user';
import { doLbrysyncRegister } from 'redux/actions/lbrysync';
import * as SETTINGS from 'constants/settings';
import Header from './view';
@ -24,6 +25,7 @@ const select = (state) => ({
const perform = (dispatch) => ({
clearEmailEntry: () => dispatch(doClearEmailEntry()),
clearPasswordEntry: () => dispatch(doClearPasswordEntry()),
lbrysyncRegister: (username, password) => dispatch(doLbrysyncRegister(username, password)),
signOut: () => dispatch(doSignOut()),
});

View file

@ -20,7 +20,7 @@ const select = (state) => ({
ffmpegStatus: selectFfmpegStatus(state),
findingFFmpeg: selectFindingFFmpeg(state),
walletEncrypted: selectWalletIsEncrypted(state),
isAuthenticated: selectUserVerifiedEmail(state),
isAuthenticated: selectUserVerifiedEmail(state), // odysee
allowAnalytics: selectAllowAnalytics(state),
});

View file

@ -497,3 +497,11 @@ export const UPDATE_UPLOAD_PROGRESS = 'UPDATE_UPLOAD_PROGRESS';
export const GENERATE_AUTH_TOKEN_FAILURE = 'GENERATE_AUTH_TOKEN_FAILURE';
export const GENERATE_AUTH_TOKEN_STARTED = 'GENERATE_AUTH_TOKEN_STARTED';
export const GENERATE_AUTH_TOKEN_SUCCESS = 'GENERATE_AUTH_TOKEN_SUCCESS';
// Lbry Sync
export const LSYNC_REGISTER_STARTED = 'LSYNC_REGISTER_STARTED';
export const LSYNC_REGISTER_COMPLETED = 'LSYNC_REGISTER_COMPLETED'; // created account
export const LSYNC_REGISTER_FAILED = 'LSYNC_REGISTER_FAILED';
export const LSYNC_AUTH_STARTED = 'LSYNC_AUTH_STARTED';
export const LSYNC_AUTH_COMPLETED = 'LSYNC_AUTH_COMPLETED'; // got token
export const LSYNC_AUTH_FAILED = 'LSYNC_AUTH_FAILED';

83
ui/lbrysync.js Normal file
View file

@ -0,0 +1,83 @@
// @flow
/*
DeriveSecrets
POST /
*/
import { LBRYSYNC_API as BASE_URL } from 'config';
const SYNC_API_DOWN = 'sync_api_down';
const DUPLICATE_EMAIL = 'duplicate_email';
const UNKNOWN_ERROR = 'unknown_api_error';
const API_VERSION = 2;
// const API_URL = `${BASE_URL}/api/${API_VERSION}`;
const AUTH_ENDPOINT = '/auth/full';
const REGISTER_ENDPOINT = '/signup';
// const WALLET_ENDPOINT = '/wallet';
const Lbrysync = {
apiRequestHeaders: { 'Content-Type': 'application/json' },
apiUrl: `${BASE_URL}/api/${API_VERSION}`,
setApiHeader: (key: string, value: string) => {
Lbrysync.apiRequestHeaders = Object.assign(Lbrysync.apiRequestHeaders, { [key]: value });
},
// store state "registered email: email"
register: async (email: string, password: string) => {
try {
const result = await callWithResult(REGISTER_ENDPOINT, { email, password });
return result;
} catch (e) {
return e.message;
}
},
// store state "lbrysynctoken: token"
getAuthToken: async (email: string, password: string, deviceId: string) => {
try {
const result = await callWithResult(AUTH_ENDPOINT, { email, password, deviceId });
return { token: result };
} catch (e) {
return { error: e.message };
}
},
};
function callWithResult(endpoint: string, params: ?{} = {}) {
return new Promise((resolve, reject) => {
apiCall(
endpoint,
params,
(result) => {
resolve(result);
},
reject
);
});
}
function apiCall(endpoint: string, params: ?{}, resolve: Function, reject: Function) {
const options = {
method: 'POST',
body: JSON.stringify(params),
};
return fetch(`${Lbrysync.apiUrl}${endpoint}`, options)
.then(handleResponse)
.then((response) => {
return resolve(response.result);
})
.catch(reject);
}
function handleResponse(response) {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response.json());
}
if (response.status === 500) {
return Promise.reject(SYNC_API_DOWN);
}
if (response.status === 409) {
return Promise.reject(DUPLICATE_EMAIL);
}
return Promise.reject(UNKNOWN_ERROR);
}
export default Lbrysync;

View file

@ -1,6 +1,7 @@
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';
import { costInfoReducer, blacklistReducer, filteredReducer, statsReducer } from 'lbryinc';
import { lbrysyncReducer } from 'redux/reducers/lbrysync';
import { claimsReducer } from 'redux/reducers/claims';
import { fileInfoReducer } from 'redux/reducers/file_info';
import { walletReducer } from 'redux/reducers/wallet';
@ -49,4 +50,5 @@ export default (history) =>
wallet: walletReducer,
sync: syncReducer,
collections: collectionsReducer,
lbrysync: lbrysyncReducer,
});

View file

@ -0,0 +1,49 @@
// @flow
import * as ACTIONS from 'constants/action_types';
import Lbrysync from 'lbrysync';
// register an email (eventually username)
export const doLbrysyncRegister = (email: string, password: string) => async (dispatch: Dispatch) => {
const { register } = Lbrysync;
// started
dispatch({
type: ACTIONS.LSYNC_REGISTER_STARTED,
});
const resultIfError = await register(email, password);
if (!resultIfError) {
dispatch({
type: ACTIONS.LSYNC_REGISTER_COMPLETED,
data: email,
});
} else {
dispatch({
type: ACTIONS.LSYNC_REGISTER_FAILED,
data: resultIfError,
});
}
};
// get token given username/password
export const doLbrysyncAuthenticate =
(email: string, password: string, deviceId: string) => async (dispatch: Dispatch) => {
const { getAuthToken } = Lbrysync;
// started
dispatch({
type: ACTIONS.LSYNC_AUTH_STARTED,
});
const result: { token?: string, error?: string } = await getAuthToken(email, password, deviceId);
if (result.token) {
dispatch({
type: ACTIONS.LSYNC_AUTH_COMPLETED,
data: result.token,
});
} else if (result.error) {
dispatch({
type: ACTIONS.LSYNC_AUTH_FAILED,
data: result.error,
});
}
};

View file

@ -0,0 +1,47 @@
import * as ACTIONS from 'constants/action_types';
import { handleActions } from 'util/redux-utils';
const defaultState = {
registering: false,
registeredEmail: null,
registerError: null,
syncProvider: null,
isAuthenticating: false,
authError: null,
authToken: null, // store this elsewhere?
};
export const lbrysyncReducer = handleActions(
{
// Register
[ACTIONS.LSYNC_REGISTER_STARTED]: (state) => ({
...state,
registering: true,
}),
[ACTIONS.LSYNC_REGISTER_COMPLETED]: (state, action) => ({
...state,
registeredEmail: action.data,
}),
[ACTIONS.LSYNC_REGISTER_FAILED]: (state) => ({
...state,
registeredEmail: null,
registering: false,
}),
// Auth
[ACTIONS.LSYNC_AUTH_STARTED]: (state) => ({
...state,
isAuthenticating: true,
}),
[ACTIONS.LSYNC_AUTH_COMPLETED]: (state, action) => ({
...state,
authToken: action.data,
}),
[ACTIONS.LSYNC_AUTH_FAILED]: (state, action) => ({
...state,
authError: action.data,
isAuthenticating: false,
}),
// ...
},
defaultState
);

View file

@ -0,0 +1,16 @@
import { createSelector } from 'reselect';
const selectState = (state) => state.lbrysync || {};
export const selectLbrySyncRegistering = createSelector(selectState, (state) => state.registering);
export const selectLbrySyncEmail = createSelector(selectState, (state) => state.registeredEmail);
export const selectLbrySyncRegisterError = createSelector(selectState, (state) => state.registerError);
// probably shouldn't store this here.
export const selectLbrySyncToken = createSelector(selectState, (state) => state.registering);
export const selectLbrySyncIsAuthenticating = createSelector(selectState, (state) => state.isAuthenticating);
export const selectLbrySyncAuthError = createSelector(selectState, (state) => state.authError);