Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/edge-login-ui-rn/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"prepare": "echo nothing to do"
},
"dependencies": {
"cleaners": "^0.3.1",
"material-ui": "^0.20.0",
"moment": "^2.19.3",
"qrcode-generator": "^1.4.4",
Expand Down
8 changes: 4 additions & 4 deletions packages/edge-login-ui-rn/src/actions/LoginInitActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,18 @@ export const initializeLogin = () => async (

// Loading is done, so send the user to the initial route:
const { previousUsers, touch } = state
const firstUser = previousUsers.lastUser
const { startupUser } = previousUsers

if (imports.recoveryKey) {
dispatch({
type: 'SET_RECOVERY_KEY',
data: imports.recoveryKey
})
} else if (firstUser == null) {
} else if (startupUser == null) {
dispatch({ type: 'WORKFLOW_START', data: 'landingWF' })
} else if (
firstUser.pinEnabled ||
(firstUser.touchEnabled && touch !== 'none')
startupUser.pinEnabled ||
(startupUser.touchEnabled && touch !== 'none')
) {
dispatch({ type: 'WORKFLOW_START', data: 'pinWF' })
} else {
Expand Down
195 changes: 97 additions & 98 deletions packages/edge-login-ui-rn/src/actions/PreviousUsersActions.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,102 @@
// @flow

import type { DiskletFolder } from 'disklet'
import { makeReactNativeDisklet } from 'disklet'
import type { EdgeContext } from 'edge-core-js'
import { asArray, asJSON, asObject, asString } from 'cleaners'
import { type Disklet, makeReactNativeDisklet } from 'disklet'

import { isTouchEnabled } from '../keychain.js'
import { type LoginUserInfo } from '../reducers/PreviousUsersReducer.js'
import { getTouchEnabledUsers, supportsTouchId } from '../keychain.js'
import {
type LoginUserInfo,
type PreviousUsersState
} from '../reducers/PreviousUsersReducer.js'
import type { Dispatch, GetState, Imports } from '../types/ReduxTypes.js'

function sortUserList(
lastUsers: string[],
userList: LoginUserInfo[]
): LoginUserInfo[] {
if (!userList || userList.length === 0) {
return []
/**
* Load the user list from core & disk into redux.
*/
export const getPreviousUsers = () => async (
dispatch: Dispatch,
getState: GetState,
imports: Imports
): Promise<void> => {
const { context, folder } = imports
const disklet = makeReactNativeDisklet()

// Load disk information:
const lastUsernames: string[] = await getRecentUsers(disklet)
const touchEnabledUsers: string[] = await getTouchEnabledUsers(folder)
const touchSupported: boolean = await supportsTouchId()

// Figure out which users have biometric logins:
const coreUsers: LoginUserInfo[] = []
for (const userInfo of context.localUsers) {
const { username, pinLoginEnabled, keyLoginEnabled = true } = userInfo
const touchEnabled =
keyLoginEnabled &&
touchSupported &&
touchEnabledUsers.indexOf(username) >= 0
coreUsers.push({ username, pinEnabled: pinLoginEnabled, touchEnabled })
}
const limitLastUsers = lastUsers.length > 0 ? lastUsers.slice(0, 3) : []
const detailedLastUsers: LoginUserInfo[] = []
for (const lastUser of limitLastUsers) {
const info = userList.find(user => user.username === lastUser)
if (info != null) detailedLastUsers.push(info)

// Move the top three users to their own list:
const topUsers: LoginUserInfo[] = []
for (const username of lastUsernames.slice(0, 3)) {
for (let i = 0; i < coreUsers.length; ++i) {
if (coreUsers[i].username === username) {
topUsers.push(coreUsers[i])
coreUsers.splice(i, 1)
break
}
}
}
const filteredUserList = userList.filter(
user => !limitLastUsers.find(lastUser => user.username === lastUser)
const userList: LoginUserInfo[] = [...topUsers, ...sortUsers(coreUsers)]

// Try to find the user requested by the LoginScreen props:
const requestedUser = userList.find(
user => user.username === imports.username
)
const sortedUserList = filteredUserList.sort((a: Object, b: Object) => {

// Dispatch to redux:
const data: PreviousUsersState = {
loaded: true,
startupUser: requestedUser != null ? requestedUser : userList[0],
userList,
usernameOnlyList: userList.map(userInfo => userInfo.username)
}
dispatch({ type: 'SET_PREVIOUS_USERS', data })
}

export const setMostRecentUsers = async (username: string) => {
const disklet = makeReactNativeDisklet()
const lastUsers = await getRecentUsers(disklet)

const filteredLastUsers = lastUsers.filter(
(lastUser: string) => lastUser !== username
)
return disklet.setText(
'lastusers.json',
JSON.stringify([username, ...filteredLastUsers])
)
}

async function getRecentUsers(disklet: Disklet): Promise<string[]> {
// Load the last users array:
try {
const lastUsernames: string[] = await disklet
.getText('lastusers.json')
.then(asLastUsersFile)
return lastUsernames
} catch (e) {}

// Fall back on the older file:
return disklet
.getText('lastuser.json')
.then(asLastUsernameFile)
.then(file => [file.username])
.catch(() => [])
}

function sortUsers(users: LoginUserInfo[]): LoginUserInfo[] {
return users.sort((a: LoginUserInfo, b: LoginUserInfo) => {
const stringA = a.username.toUpperCase()
const stringB = b.username.toUpperCase()
if (stringA < stringB) {
Expand All @@ -35,84 +107,11 @@ function sortUserList(
}
return 0
})

return [...detailedLastUsers, ...sortedUserList]
}

async function getDiskStuff(context: EdgeContext, folder: DiskletFolder) {
const userList = await context.listUsernames().then(usernames =>
Promise.all(
usernames.map(username => {
return context.pinLoginEnabled(username).then(async pinEnabled => {
return {
username,
pinEnabled,
touchEnabled: await isTouchEnabled(folder, username)
}
})
})
)
)

const disklet = makeReactNativeDisklet()
const lastUsers = await disklet
.getText('lastusers.json')
.then(text => JSON.parse(text))
.catch(_ => [])
if (lastUsers && lastUsers.length > 0) {
return {
lastUser: lastUsers[0],
userList: sortUserList(lastUsers, userList)
}
}
const lastUser = await disklet
.getText('lastuser.json')
.then(text => JSON.parse(text))
.then(json => (json && json.username ? json.username : ''))
.catch(_ => '')
return {
lastUser,
userList: sortUserList([lastUser], userList)
}
}

export function getPreviousUsers() {
return async (dispatch: Dispatch, getState: GetState, imports: Imports) => {
const { context, folder, username } = imports
await getDiskStuff(context, folder).then((data: Object) => {
const focusUser = username || data.lastUser
if (data.userList && data.userList.length > 0) {
data.usernameOnlyList = []
data.userList.forEach(function(element) {
if (element.username === focusUser) {
data.lastUser = {
username: focusUser,
pinEnabled: element.pinEnabled,
touchEnabled: element.touchEnabled
}
}
data.usernameOnlyList.push(element.username)
}, this)
}
dispatch({ type: 'SET_PREVIOUS_USERS', data: data })
})
}
}

export const setMostRecentUsers = async (username: string) => {
const disklet = makeReactNativeDisklet()
const lastUsers = await disklet
.getText('lastusers.json')
.then(text => JSON.parse(text))
.catch(_ => [])
if (lastUsers && lastUsers.length > 0) {
const filteredLastUsers = lastUsers.filter(
(lastUser: string) => lastUser !== username
)
return disklet.setText(
'lastusers.json',
JSON.stringify([username, ...filteredLastUsers])
)
}
return disklet.setText('lastusers.json', JSON.stringify([username]))
}
const asLastUsersFile = asJSON(asArray(asString))
const asLastUsernameFile = asJSON(
asObject({
username: asString
})
)
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ import { StaticModal } from '../common/StaticModal.js'
import { DeleteUserModal } from '../modals/DeleteUserModal.js'
import { connect } from '../services/ReduxStore.js'

const Offsets = {
USERNAME_OFFSET_LOGIN_SCREEN: -50,
PASSWORD_OFFSET_LOGIN_SCREEN: -80,
LOGIN_SCREEN_NO_OFFSET: -200
}

type OwnProps = {
appId?: string,
backgroundImage?: any,
Expand All @@ -38,7 +32,6 @@ type OwnProps = {
}
type StateProps = {
error: string,
hasUsers: boolean,
loginSuccess: boolean,
password: string,
previousUsers: LoginUserInfo[],
Expand All @@ -64,7 +57,6 @@ type State = {
loggingIn: boolean,
focusFirst: boolean,
focusSecond: boolean,
offset: number,
showRecoveryModalOne: boolean,
showRecoveryModalTwo: boolean,
usernameList: boolean
Expand All @@ -85,7 +77,6 @@ class PasswordLoginScreenComponent extends Component<Props, State> {
loggingIn: false,
focusFirst: true,
focusSecond: false,
offset: Offsets.USERNAME_OFFSET_LOGIN_SCREEN,
showRecoveryModalOne: false,
showRecoveryModalTwo: false,
usernameList: false
Expand Down Expand Up @@ -128,8 +119,7 @@ class PasswordLoginScreenComponent extends Component<Props, State> {
Keyboard.dismiss()
this.setState({
focusFirst: false,
focusSecond: false,
offset: Offsets.LOGIN_SCREEN_NO_OFFSET
focusSecond: false
})
}

Expand All @@ -156,8 +146,7 @@ class PasswordLoginScreenComponent extends Component<Props, State> {
password: '',
loggingIn: false,
focusFirst: true,
focusSecond: false,
offset: Offsets.USERNAME_OFFSET_LOGIN_SCREEN
focusSecond: false
})
}

Expand Down Expand Up @@ -350,26 +339,21 @@ class PasswordLoginScreenComponent extends Component<Props, State> {
onfocusOne() {
this.setState({
focusFirst: true,
focusSecond: false,
offset: this.props.hasUsers
? Offsets.USERNAME_OFFSET_LOGIN_SCREEN
: Offsets.LOGIN_SCREEN_NO_OFFSET
focusSecond: false
})
}

onfocusTwo() {
this.setState({
focusFirst: false,
focusSecond: true,
offset: Offsets.PASSWORD_OFFSET_LOGIN_SCREEN
focusSecond: true
})
}

onSetNextFocus() {
this.setState({
focusFirst: false,
focusSecond: true,
offset: Offsets.PASSWORD_OFFSET_LOGIN_SCREEN
focusSecond: true
})
}

Expand Down Expand Up @@ -557,7 +541,6 @@ const LoginPasswordScreenStyle = {
export const PasswordLoginScreen = connect<StateProps, DispatchProps, OwnProps>(
(state: RootState) => ({
error: state.login.errorMessage || '',
hasUsers: state.previousUsers.userList.length > 0,
loginSuccess: state.login.loginSuccess,
password: state.login.password || '',
previousUsers: state.previousUsers.userList,
Expand Down
2 changes: 2 additions & 0 deletions packages/edge-login-ui-rn/src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// @flow

import './util/androidFetch.js'

export * from './components/publicApi/ChangePasswordScreen.js'
export * from './components/publicApi/ChangePinScreen.js'
export * from './components/publicApi/ChooseTestAppScreen.js'
Expand Down
Loading