168 lines
5.0 KiB
JavaScript
168 lines
5.0 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
import { render, Box, Text, useApp, useInput } from 'ink';
|
|
import TextInput from 'ink-text-input';
|
|
import chalk from 'chalk';
|
|
import * as googleAuth from '../src/db/googleAuth.js';
|
|
|
|
import '../src/config/env.js';
|
|
|
|
const e = React.createElement;
|
|
|
|
const MODES = {
|
|
MENU: 'menu',
|
|
ADD: 'add',
|
|
REMOVE: 'remove',
|
|
LIST: 'list',
|
|
DONE: 'done',
|
|
ERROR: 'error',
|
|
};
|
|
|
|
const Menu = ({ onSelect }) => {
|
|
const [selected, setSelected] = useState(0);
|
|
const options = [
|
|
{ label: 'List allowed emails', value: 'list' },
|
|
{ label: 'Add email', value: 'add' },
|
|
{ label: 'Remove email', value: 'remove' },
|
|
{ label: 'Quit', value: 'quit' },
|
|
];
|
|
|
|
useInput((_input, key) => {
|
|
if (key.upArrow) setSelected((s) => Math.max(0, s - 1));
|
|
if (key.downArrow) setSelected((s) => Math.min(options.length - 1, s + 1));
|
|
if (key.return) onSelect(options[selected].value);
|
|
});
|
|
|
|
return e(Box, { flexDirection: 'column' },
|
|
options.map((opt, i) =>
|
|
e(Text, { key: opt.value },
|
|
i === selected ? chalk.cyan('> ') : ' ',
|
|
i === selected ? chalk.cyan.bold(opt.label) : opt.label
|
|
)
|
|
)
|
|
);
|
|
};
|
|
|
|
const App = () => {
|
|
const { exit } = useApp();
|
|
const [mode, setMode] = useState(MODES.MENU);
|
|
const [email, setEmail] = useState('');
|
|
const [message, setMessage] = useState('');
|
|
const [error, setError] = useState('');
|
|
const [emails, setEmails] = useState(null);
|
|
|
|
useEffect(() => {
|
|
if (mode !== MODES.LIST) {
|
|
return;
|
|
}
|
|
setEmails(null);
|
|
googleAuth.listAllowedEmails()
|
|
.then(setEmails)
|
|
.catch((err) => finish(false, err.message));
|
|
}, [mode]);
|
|
|
|
const finish = (success, text) => {
|
|
if (success) {
|
|
setMessage(text);
|
|
setMode(MODES.DONE);
|
|
} else {
|
|
setError(text);
|
|
setMode(MODES.ERROR);
|
|
}
|
|
setTimeout(() => {
|
|
exit();
|
|
process.exit(success ? 0 : 1);
|
|
}, 100);
|
|
};
|
|
|
|
const handleMenu = (action) => {
|
|
if (action === 'quit') {
|
|
exit();
|
|
process.exit(0);
|
|
}
|
|
setEmail('');
|
|
setMode(action);
|
|
};
|
|
|
|
const handleAdd = async () => {
|
|
try {
|
|
const trimmed = email.trim();
|
|
if (!trimmed || !trimmed.includes('@')) {
|
|
finish(false, 'Invalid email address');
|
|
return;
|
|
}
|
|
await googleAuth.addAllowedEmail(trimmed);
|
|
finish(true, `Added ${trimmed.toLowerCase()} to google_auth`);
|
|
} catch (err) {
|
|
finish(false, err.message);
|
|
}
|
|
};
|
|
|
|
const handleRemove = async () => {
|
|
try {
|
|
const trimmed = email.trim();
|
|
if (!trimmed) {
|
|
finish(false, 'Email is required');
|
|
return;
|
|
}
|
|
const removed = await googleAuth.removeAllowedEmail(trimmed);
|
|
finish(true, removed ? `Removed ${trimmed.toLowerCase()}` : `Email not found: ${trimmed}`);
|
|
} catch (err) {
|
|
finish(false, err.message);
|
|
}
|
|
};
|
|
|
|
if (mode === MODES.DONE) {
|
|
return e(Text, null, chalk.green(message));
|
|
}
|
|
if (mode === MODES.ERROR) {
|
|
return e(Text, null, chalk.red(`Error: ${error}`));
|
|
}
|
|
if (mode === MODES.LIST) {
|
|
if (!emails) {
|
|
return e(Text, null, chalk.gray('Loading...'));
|
|
}
|
|
if (emails.length === 0) {
|
|
finish(true, 'No allowed emails in google_auth');
|
|
return e(Text, null, chalk.yellow('No allowed emails...'));
|
|
}
|
|
return e(Box, { flexDirection: 'column' },
|
|
e(Text, null, chalk.cyan.bold('Allowed emails:')),
|
|
...emails.map((row) => e(Text, { key: row.id }, ` ${row.email}`)),
|
|
e(Box, { marginTop: 1 }, e(Text, null, chalk.gray('Press any key to exit'))),
|
|
e(ExitOnKey, { onExit: () => { exit(); process.exit(0); } })
|
|
);
|
|
}
|
|
if (mode === MODES.ADD) {
|
|
return e(Box, { flexDirection: 'column' },
|
|
e(Text, null, chalk.cyan.bold('Add allowed email')),
|
|
e(Box, null,
|
|
e(Text, null, 'Email: '),
|
|
e(TextInput, { value: email, onChange: setEmail, onSubmit: handleAdd })
|
|
)
|
|
);
|
|
}
|
|
if (mode === MODES.REMOVE) {
|
|
return e(Box, { flexDirection: 'column' },
|
|
e(Text, null, chalk.cyan.bold('Remove allowed email')),
|
|
e(Box, null,
|
|
e(Text, null, 'Email: '),
|
|
e(TextInput, { value: email, onChange: setEmail, onSubmit: handleRemove })
|
|
)
|
|
);
|
|
}
|
|
|
|
return e(Box, { flexDirection: 'column' },
|
|
e(Box, { marginBottom: 1 },
|
|
e(Text, null, chalk.cyan.bold('=== Google Auth Email Manager ==='))
|
|
),
|
|
e(Menu, { onSelect: handleMenu })
|
|
);
|
|
};
|
|
|
|
const ExitOnKey = ({ onExit }) => {
|
|
useInput(onExit);
|
|
return null;
|
|
};
|
|
|
|
render(e(App));
|