mirror of
https://github.com/balzack/databag.git
synced 2025-03-13 00:50:03 +00:00
implementing account management
This commit is contained in:
parent
f798dfe689
commit
db77fbd0a4
@ -1,31 +1,105 @@
|
||||
import React, {useState} from 'react';
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import {FlatList, SafeAreaView, Image, View, Pressable} from 'react-native';
|
||||
import {Text, IconButton, Divider, Surface, useTheme} from 'react-native-paper';
|
||||
import {useAccounts} from './useAccounts.hook';
|
||||
import {styles} from './Accounts.styled';
|
||||
import { Card } from '../card/Card';
|
||||
import { Colors } from '../constants/Colors';
|
||||
import { Confirm } from '../confirm/Confirm';
|
||||
|
||||
export function Accounts({ setup }: { setup: ()=>void }) {
|
||||
const { state, actions } = useAccounts();
|
||||
const theme = useTheme();
|
||||
const [loading, setLoading] = useState('');
|
||||
const [failed, setFailed] = useState(false);
|
||||
const [remove, setRemove] = useState(null);
|
||||
const [removeParams, setRemoveParams] = useState({});
|
||||
const [removing, setRemoving] = useState(null);
|
||||
const [blocking, setBlocking] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
loadAccounts();
|
||||
}, []);
|
||||
|
||||
const loadAccounts = async () => {
|
||||
if (!loading) {
|
||||
setLoading(true);
|
||||
try {
|
||||
await actions.reload();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
const failedParams = {
|
||||
title: state.strings.operationFailed,
|
||||
prompt: state.strings.tryAgain,
|
||||
cancel: {
|
||||
label: state.strings.close,
|
||||
action: ()=>{setFailed(false)},
|
||||
},
|
||||
};
|
||||
|
||||
const blockAccount = async (accountId: number, block: boolean) => {
|
||||
if (!blocking) {
|
||||
setBlocking(accountId);
|
||||
try {
|
||||
await actions.blockAccount(accountId, block);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
setFailed(true);
|
||||
}
|
||||
setBlocking(null);
|
||||
}
|
||||
}
|
||||
|
||||
const removeAccount = (accountId: number) => {
|
||||
if (!remove) {
|
||||
setRemoveParams({
|
||||
title: state.strings.confirmDelete,
|
||||
prompt: state.strings.areSure,
|
||||
confirm: {
|
||||
label: state.strings.remove,
|
||||
action: async () => {
|
||||
if (!removing) {
|
||||
setRemoving(accountId);
|
||||
try {
|
||||
await actions.removeAccount(accountId);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
setFailed(true);
|
||||
}
|
||||
setRemoving(false);
|
||||
setRemove(false);
|
||||
}
|
||||
},
|
||||
},
|
||||
cancel: {
|
||||
label: state.strings.cancel,
|
||||
action: () => {setRemove(false)},
|
||||
},
|
||||
})
|
||||
setRemove(true);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.accounts}>
|
||||
{ state.layout === 'large' && (
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.largeTitle}>{ state.strings.accounts }</Text>
|
||||
<IconButton style={styles.icon} loading={loading} iconColor={Colors.primary} mode="contained" icon="refresh" onPress={()=>{}} />
|
||||
<IconButton style={styles.icon} loading={loading} iconColor={Colors.primary} mode="contained" icon="account-plus-outline" onPress={()=>{}} />
|
||||
<IconButton style={styles.icon} loading={loading} iconColor={Colors.primary} mode="contained" icon="cog-outline" onPress={setup} />
|
||||
<IconButton style={styles.icon} loading={loading} iconColor={Colors.primary} mode="contained" icon="refresh" onPress={loadAccounts} />
|
||||
<IconButton style={styles.icon} loading={false} iconColor={Colors.primary} mode="contained" icon="account-plus-outline" onPress={()=>{}} />
|
||||
<IconButton style={styles.icon} loading={false} iconColor={Colors.primary} mode="contained" icon="cog-outline" onPress={setup} />
|
||||
</View>
|
||||
)}
|
||||
{ state.layout === 'small' && (
|
||||
<View style={styles.header}>
|
||||
<IconButton style={styles.icon} loading={loading} iconColor={Colors.primary} mode="contained" icon="refresh" onPress={()=>{}} />
|
||||
<IconButton style={styles.icon} loading={loading} iconColor={Colors.primary} mode="contained" icon="refresh" onPress={loadAccounts} />
|
||||
<Text style={styles.smallTitle}>{ state.strings.accounts }</Text>
|
||||
<IconButton style={styles.icon} loading={loading} iconColor={Colors.primary} mode="contained" icon="account-plus-outline" onPress={()=>{}} />
|
||||
<IconButton style={styles.icon} loading={false} iconColor={Colors.primary} mode="contained" icon="account-plus-outline" onPress={()=>{}} />
|
||||
</View>
|
||||
)}
|
||||
<Divider style={styles.line} bold={true} />
|
||||
@ -37,9 +111,9 @@ export function Accounts({ setup }: { setup: ()=>void }) {
|
||||
showsVerticalScrollIndicator={false}
|
||||
renderItem={({item}) => {
|
||||
const options = [
|
||||
<IconButton key="disable" style={styles.icon} loading={loading} iconColor={Colors.primary} mode="contained" icon="lock-open-variant-outline" onPress={()=>{}} />,
|
||||
<IconButton key="reset" style={styles.icon} loading={loading} iconColor={Colors.pending} mode="contained" icon="account-cancel-outline" onPress={()=>{}} />,
|
||||
<IconButton key="remove" style={styles.icon} loading={loading} iconColor={Colors.offsync} mode="contained" icon="trash-can-outline" onPress={()=>{}} />
|
||||
<IconButton key="disable" style={styles.icon} loading={false} iconColor={Colors.primary} mode="contained" icon="lock-open-variant-outline" onPress={()=>{}} />,
|
||||
<IconButton key="reset" style={styles.icon} loading={blocking === item.accountId} iconColor={Colors.pending} mode="contained" icon={item.disabled ? 'account-check-outline' : 'account-cancel-outline'} onPress={()=>{blockAccount(item.accountId, !item.disabled)}} />,
|
||||
<IconButton key="remove" style={styles.icon} loading={removing === item.accountId} iconColor={Colors.offsync} mode="contained" icon="trash-can-outline" onPress={()=>{removeAccount(item.accountId)}} />
|
||||
];
|
||||
return (
|
||||
<Card
|
||||
@ -64,6 +138,8 @@ export function Accounts({ setup }: { setup: ()=>void }) {
|
||||
</View>
|
||||
)}
|
||||
<Divider style={styles.line} bold={true} />
|
||||
<Confirm show={failed} params={failedParams} />
|
||||
<Confirm show={remove} busy={removing} params={removeParams} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ export function useAccounts() {
|
||||
layout: '',
|
||||
strings: {},
|
||||
members: [] as Member[],
|
||||
loading: false,
|
||||
});
|
||||
|
||||
const updateState = (value: any) => {
|
||||
@ -18,12 +19,16 @@ export function useAccounts() {
|
||||
};
|
||||
|
||||
const sync = async () => {
|
||||
try {
|
||||
const service = app.state.service;
|
||||
const members = await service.getMembers();
|
||||
updateState({ members });
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
if (!state.loading) {
|
||||
try {
|
||||
updateState({ loading: true });
|
||||
const service = app.state.service;
|
||||
const members = await service.getMembers();
|
||||
updateState({ members, loading: false });
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
updateState({ loading: false });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,13 +37,22 @@ export function useAccounts() {
|
||||
updateState({ layout, strings});
|
||||
}, [display.state]);
|
||||
|
||||
useEffect(() => {
|
||||
if (app.state.service) {
|
||||
sync();
|
||||
}
|
||||
}, [app.state.service]);
|
||||
|
||||
const actions = {
|
||||
reload: sync,
|
||||
addAccount: async () => {
|
||||
return await app.state.service.createMemberAccess();
|
||||
},
|
||||
accessAccount: async (accountId: number) => {
|
||||
return await app.state.service.resetMemberAccess(accoutId);
|
||||
},
|
||||
blockAccount: async (accountId: number, flag: boolean) => {
|
||||
await app.state.service.blockMember(accountId, flag);
|
||||
await sync();
|
||||
},
|
||||
removeAccount: async (accountId: number) => {
|
||||
await app.state.service.removeMember(accountId);
|
||||
await sync();
|
||||
},
|
||||
};
|
||||
|
||||
return {state, actions};
|
||||
|
@ -22,7 +22,7 @@ export function Confirm({show, busy, params}) {
|
||||
{params.prompt && <Text style={styles.prompt}>{params.prompt}</Text>}
|
||||
<View style={styles.controls}>
|
||||
{params.cancel && (
|
||||
<Button mode="outlined" onPress={params.cancel.action}>
|
||||
<Button mode="outlined" disabled={busy} onPress={params.cancel.action}>
|
||||
{params.cancel.label}
|
||||
</Button>
|
||||
)}
|
||||
|
@ -18,8 +18,6 @@ export function Setup() {
|
||||
},
|
||||
};
|
||||
|
||||
console.log(state.setup);
|
||||
|
||||
return (
|
||||
<View style={styles.setup}>
|
||||
<View style={styles.header}>
|
||||
|
@ -164,8 +164,8 @@ export interface Focus {
|
||||
export interface Service {
|
||||
getMembers(): Promise<Member[]>;
|
||||
createMemberAccess(): Promise<string>;
|
||||
resetMemberAccess(): Promise<string>;
|
||||
blockMember(flag: boolean): Promise<void>;
|
||||
resetMemberAccess(accontId: number): Promise<string>;
|
||||
blockMember(accountId: number, flag: boolean): Promise<void>;
|
||||
removeMember(accountId: number): Promise<void>;
|
||||
getSetup(): Promise<Setup>;
|
||||
setSetup(setup: Setup): Promise<void>;
|
||||
|
9
app/sdk/src/net/addNodeAccount.ts
Normal file
9
app/sdk/src/net/addNodeAccount.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function addNodeAccount(server: string, secure: boolean, token: string): Promise<string> {
|
||||
const endpoint = `http${secure ? 's' : ''}://${server}/admin/accounts?token=${token}`;
|
||||
const create = await fetchWithTimeout(endpoint, { method: 'POST' });
|
||||
checkResponse(create.status);
|
||||
return await create.json();
|
||||
}
|
||||
|
8
app/sdk/src/net/addNodeAccountAccess.ts
Normal file
8
app/sdk/src/net/addNodeAccountAccess.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function addNodeAccountAccess(server: string, secure: boolean, token: string, accountId: number): Promise<string> {
|
||||
const endpoint = `http${secure ? 's' : ''}://${server}/admin/accounts/${accountId}/auth?token=${token}`;
|
||||
const access = await fetchWithTimeout(endpoint, { method: 'POST' });
|
||||
checkResponse(access.status);
|
||||
return await access.json();
|
||||
}
|
7
app/sdk/src/net/removeNodeAccount.ts
Normal file
7
app/sdk/src/net/removeNodeAccount.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function removeNodeAccount(server: string, secure: boolean, token: string, accountId: number) {
|
||||
const endpoint = `http${secure ? 's' : ''}://${server}/admin/accounts/${accountId}?token=${token}`;
|
||||
const { status } = await fetchWithTimeout(endpoint, { method: 'DELETE' });
|
||||
checkResponse(status);
|
||||
}
|
7
app/sdk/src/net/setNodeAccount.ts
Normal file
7
app/sdk/src/net/setNodeAccount.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function setNodeAccount(server: string, secure: boolean, token: string, accountId: number, disabled: boolean) {
|
||||
const endpoint = `http${secure ? 's' : ''}://${server}/admin/accounts/${accountId}/status?token=${token}`;
|
||||
const { status } = await fetchWithTimeout(endpoint, { method: 'PUT', body: JSON.stringify(disabled) });
|
||||
checkResponse(status);
|
||||
}
|
@ -10,6 +10,10 @@ import { addAdminMFAuth } from './net/addAdminMFAuth';
|
||||
import { removeAdminMFAuth } from './net/removeAdminMFAuth';
|
||||
import { getNodeConfig } from './net/getNodeConfig';
|
||||
import { setNodeConfig } from './net/setNodeConfig';
|
||||
import { addNodeAccount } from './net/addNodeAccount';
|
||||
import { addNodeAccountAccess } from './net/addNodeAccountAccess';
|
||||
import { removeNodeAccount } from './net/removeNodeAccount';
|
||||
import { setNodeAccount } from './net/setNodeAccount';
|
||||
|
||||
export class ServiceModule implements Service {
|
||||
private log: Logging;
|
||||
@ -25,16 +29,24 @@ export class ServiceModule implements Service {
|
||||
}
|
||||
|
||||
public async createMemberAccess(): Promise<string> {
|
||||
return '';
|
||||
const { node, secure, token } = this;
|
||||
return await addNodeAccount(node, secure, token);
|
||||
}
|
||||
|
||||
public async resetMemberAccess(): Promise<string> {
|
||||
return '';
|
||||
public async resetMemberAccess(accountId: number): Promise<string> {
|
||||
const { node, secure, token } = this;
|
||||
return await addNodeAccountAccess(node, secure, token, accountId);
|
||||
}
|
||||
|
||||
public async blockMember(flag: boolean): Promise<void> {}
|
||||
public async blockMember(accountId: number, flag: boolean): Promise<void> {
|
||||
const { node, secure, token } = this;
|
||||
await setNodeAccount(node, secure, token, accountId, flag);
|
||||
}
|
||||
|
||||
public async removeMember(accountId: number): Promise<void> {}
|
||||
public async removeMember(accountId: number): Promise<void> {
|
||||
const { node, secure, token } = this;
|
||||
await removeNodeAccount(node, secure, token, accountId);
|
||||
}
|
||||
|
||||
public async getMembers(): Promise<Member[]> {
|
||||
const { node, secure, token } = this;
|
||||
@ -42,7 +54,7 @@ export class ServiceModule implements Service {
|
||||
return accounts.map(account => {
|
||||
const { accountId, guid, handle, name, imageSet, revision, disabled, storageUsed } = account;
|
||||
const imageUrl = imageSet ? getMemberImageUrl(node, secure, token, accountId, revision) : avatar;
|
||||
return { accountId, guid, handle, name, imageUrl, storageUsed };
|
||||
return { accountId, guid, handle, name, imageUrl, disabled, storageUsed };
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user