mirror of
https://github.com/Qortal/chrome-extension.git
synced 2025-04-24 20:07:52 +00:00
added admin action qortalrequest
This commit is contained in:
parent
a625a2ce67
commit
95df97ba19
@ -629,7 +629,7 @@ function App() {
|
|||||||
if (message.action === "QORTAL_REQUEST_PERMISSION" && isMainWindow) {
|
if (message.action === "QORTAL_REQUEST_PERMISSION" && isMainWindow) {
|
||||||
try {
|
try {
|
||||||
if(message?.payload?.checkbox1){
|
if(message?.payload?.checkbox1){
|
||||||
qortalRequestCheckbox1Ref.current = message?.payload?.checkbox1
|
qortalRequestCheckbox1Ref.current = message?.payload?.checkbox1?.value || false
|
||||||
}
|
}
|
||||||
await showQortalRequestExtension(message?.payload);
|
await showQortalRequestExtension(message?.payload);
|
||||||
|
|
||||||
|
@ -28,6 +28,14 @@ export const sortablePinnedAppsAtom = atom({
|
|||||||
{
|
{
|
||||||
name: 'Q-Trade',
|
name: 'Q-Trade',
|
||||||
service: 'APP'
|
service: 'APP'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Q-Support',
|
||||||
|
service: 'APP'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'NodeInfo',
|
||||||
|
service: 'APP'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
@ -15,7 +15,7 @@ export const AppViewer = React.forwardRef(({ app , hide}, iframeRef) => {
|
|||||||
const { rootHeight } = useContext(MyContext);
|
const { rootHeight } = useContext(MyContext);
|
||||||
// const iframeRef = useRef(null);
|
// const iframeRef = useRef(null);
|
||||||
const { document, window: frameWindow } = useFrame();
|
const { document, window: frameWindow } = useFrame();
|
||||||
const {path, history, changeCurrentIndex} = useQortalMessageListener(frameWindow, iframeRef, app?.tabId)
|
const {path, history, changeCurrentIndex} = useQortalMessageListener(frameWindow, iframeRef, app?.tabId, app?.name, app?.service)
|
||||||
const [url, setUrl] = useState('')
|
const [url, setUrl] = useState('')
|
||||||
|
|
||||||
useEffect(()=> {
|
useEffect(()=> {
|
||||||
|
@ -42,7 +42,9 @@ const officialAppList = [
|
|||||||
"qombo",
|
"qombo",
|
||||||
"q-fund",
|
"q-fund",
|
||||||
"q-shop",
|
"q-shop",
|
||||||
"q-trade"
|
"q-trade",
|
||||||
|
"q-support",
|
||||||
|
"NodeInfo"
|
||||||
];
|
];
|
||||||
|
|
||||||
const ScrollerStyled = styled('div')({
|
const ScrollerStyled = styled('div')({
|
||||||
|
@ -57,7 +57,9 @@ const officialAppList = [
|
|||||||
"qombo",
|
"qombo",
|
||||||
"q-fund",
|
"q-fund",
|
||||||
"q-shop",
|
"q-shop",
|
||||||
"q-trade"
|
"q-trade",
|
||||||
|
"q-support",
|
||||||
|
"NodeInfo"
|
||||||
];
|
];
|
||||||
|
|
||||||
const ScrollerStyled = styled("div")({
|
const ScrollerStyled = styled("div")({
|
||||||
|
@ -140,7 +140,7 @@ const UIQortalRequests = [
|
|||||||
'GET_TX_ACTIVITY_SUMMARY', 'GET_FOREIGN_FEE', 'UPDATE_FOREIGN_FEE',
|
'GET_TX_ACTIVITY_SUMMARY', 'GET_FOREIGN_FEE', 'UPDATE_FOREIGN_FEE',
|
||||||
'GET_SERVER_CONNECTION_HISTORY', 'SET_CURRENT_FOREIGN_SERVER',
|
'GET_SERVER_CONNECTION_HISTORY', 'SET_CURRENT_FOREIGN_SERVER',
|
||||||
'ADD_FOREIGN_SERVER', 'REMOVE_FOREIGN_SERVER', 'GET_DAY_SUMMARY', 'CREATE_TRADE_BUY_ORDER',
|
'ADD_FOREIGN_SERVER', 'REMOVE_FOREIGN_SERVER', 'GET_DAY_SUMMARY', 'CREATE_TRADE_BUY_ORDER',
|
||||||
'CREATE_TRADE_SELL_ORDER', 'CANCEL_TRADE_SELL_ORDER', 'IS_USING_GATEWAY'
|
'CREATE_TRADE_SELL_ORDER', 'CANCEL_TRADE_SELL_ORDER', 'IS_USING_GATEWAY', 'ADMIN_ACTION'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
@ -317,7 +317,7 @@ const UIQortalRequests = [
|
|||||||
return obj; // Updated object with references to stored files
|
return obj; // Updated object with references to stored files
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useQortalMessageListener = (frameWindow, iframeRef, tabId) => {
|
export const useQortalMessageListener = (frameWindow, iframeRef, tabId, appName, appService) => {
|
||||||
const [path, setPath] = useState('')
|
const [path, setPath] = useState('')
|
||||||
const [history, setHistory] = useState({
|
const [history, setHistory] = useState({
|
||||||
customQDNHistoryPaths: [],
|
customQDNHistoryPaths: [],
|
||||||
@ -387,7 +387,9 @@ isDOMContentLoaded: false
|
|||||||
// Check if action is included in the predefined list of UI requests
|
// Check if action is included in the predefined list of UI requests
|
||||||
if (UIQortalRequests.includes(event.data.action)) {
|
if (UIQortalRequests.includes(event.data.action)) {
|
||||||
sendMessageToRuntime(
|
sendMessageToRuntime(
|
||||||
{ action: event.data.action, type: 'qortalRequest', payload: event.data, isExtension: true },
|
{ action: event.data.action, type: 'qortalRequest', payload: event.data, isExtension: true, appInfo: {
|
||||||
|
name: appName, service: appService
|
||||||
|
} },
|
||||||
event.ports[0]
|
event.ports[0]
|
||||||
);
|
);
|
||||||
} else if (
|
} else if (
|
||||||
@ -465,7 +467,7 @@ isDOMContentLoaded: false
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}, []); // Empty dependency array to run once when the component mounts
|
}, [appName, appService]); // Empty dependency array to run once when the component mounts
|
||||||
|
|
||||||
chrome.runtime?.onMessage.addListener( function (message, sender, sendResponse) {
|
chrome.runtime?.onMessage.addListener( function (message, sender, sendResponse) {
|
||||||
if(message.action === "SHOW_SAVE_FILE_PICKER"){
|
if(message.action === "SHOW_SAVE_FILE_PICKER"){
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { getApiKeyFromStorage } from "./background";
|
import { getApiKeyFromStorage } from "./background";
|
||||||
import { addForeignServer, addListItems, cancelSellOrder, createBuyOrder, createPoll, createSellOrder, decryptData, deleteListItems, deployAt, encryptData, getCrossChainServerInfo, getDaySummary, getForeignFee, getListItems, getServerConnectionHistory, getTxActivitySummary, getUserAccount, getUserWallet, getUserWalletInfo, getWalletBalance, joinGroup, publishMultipleQDNResources, publishQDNResource, removeForeignServer, saveFile, sendChatMessage, sendCoin, setCurrentForeignServer, updateForeignFee, voteOnPoll } from "./qortalRequests/get";
|
import { addForeignServer, addListItems, adminAction, cancelSellOrder, createBuyOrder, createPoll, createSellOrder, decryptData, deleteListItems, deployAt, encryptData, getCrossChainServerInfo, getDaySummary, getForeignFee, getListItems, getServerConnectionHistory, getTxActivitySummary, getUserAccount, getUserWallet, getUserWalletInfo, getWalletBalance, joinGroup, publishMultipleQDNResources, publishQDNResource, removeForeignServer, saveFile, sendChatMessage, sendCoin, setCurrentForeignServer, updateForeignFee, voteOnPoll } from "./qortalRequests/get";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -74,9 +74,10 @@ function getLocalStorage(key) {
|
|||||||
chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => {
|
chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => {
|
||||||
if (request) {
|
if (request) {
|
||||||
const isFromExtension = request?.isExtension
|
const isFromExtension = request?.isExtension
|
||||||
|
const appInfo = request?.appInfo;
|
||||||
switch (request.action) {
|
switch (request.action) {
|
||||||
case "GET_USER_ACCOUNT": {
|
case "GET_USER_ACCOUNT": {
|
||||||
getUserAccount()
|
getUserAccount({isFromExtension, appInfo})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
sendResponse(res);
|
sendResponse(res);
|
||||||
})
|
})
|
||||||
@ -270,7 +271,7 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => {
|
|||||||
case "GET_WALLET_BALANCE": {
|
case "GET_WALLET_BALANCE": {
|
||||||
const data = request.payload;
|
const data = request.payload;
|
||||||
|
|
||||||
getWalletBalance(data, false, isFromExtension)
|
getWalletBalance(data, false, isFromExtension, appInfo)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
sendResponse(res);
|
sendResponse(res);
|
||||||
})
|
})
|
||||||
@ -477,6 +478,17 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "ADMIN_ACTION": {
|
||||||
|
adminAction(data, isFromExtension).then((res) => {
|
||||||
|
sendResponse(res);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
sendResponse({ error: error?.message });
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -364,8 +364,30 @@ async function getUserPermission(payload: any, isFromExtension?: boolean) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUserAccount = async () => {
|
export const getUserAccount = async ({isFromExtension, appInfo}) => {
|
||||||
try {
|
try {
|
||||||
|
const value = (await getPermission(`qAPPAutoAuth-${appInfo?.name}`)) || false;
|
||||||
|
let skip = false;
|
||||||
|
if (value) {
|
||||||
|
skip = true;
|
||||||
|
}
|
||||||
|
let resPermission
|
||||||
|
if(!skip){
|
||||||
|
resPermission = await getUserPermission({
|
||||||
|
text1: "Do you give this application permission to authenticate?",
|
||||||
|
checkbox1: {
|
||||||
|
value: false,
|
||||||
|
label: "Always authenticate automatically",
|
||||||
|
},
|
||||||
|
}, isFromExtension);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { accepted = false, checkbox1 = false } = resPermission || {};
|
||||||
|
if(resPermission){
|
||||||
|
setPermission(`qAPPAutoAuth-${appInfo?.name}`, checkbox1);
|
||||||
|
}
|
||||||
|
if (accepted || skip) {
|
||||||
|
|
||||||
const wallet = await getSaveWallet();
|
const wallet = await getSaveWallet();
|
||||||
const address = wallet.address0;
|
const address = wallet.address0;
|
||||||
const publicKey = wallet.publicKey;
|
const publicKey = wallet.publicKey;
|
||||||
@ -373,7 +395,12 @@ export const getUserAccount = async () => {
|
|||||||
address,
|
address,
|
||||||
publicKey,
|
publicKey,
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
throw new Error("User declined request");
|
||||||
|
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log('per error', error)
|
||||||
throw new Error("Unable to fetch user account");
|
throw new Error("Unable to fetch user account");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -447,8 +474,10 @@ export const decryptData = async (data) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getListItems = async (data, isFromExtension) => {
|
export const getListItems = async (data, isFromExtension) => {
|
||||||
const localNodeAvailable = await isUsingLocal()
|
const isGateway = await isRunningGateway()
|
||||||
if(!localNodeAvailable) throw new Error('Please use your local node.')
|
if(isGateway){
|
||||||
|
throw new Error('This action cannot be done through a gateway')
|
||||||
|
}
|
||||||
const requiredFields = ["list_name"];
|
const requiredFields = ["list_name"];
|
||||||
const missingFields: string[] = [];
|
const missingFields: string[] = [];
|
||||||
requiredFields.forEach((field) => {
|
requiredFields.forEach((field) => {
|
||||||
@ -499,8 +528,10 @@ export const getListItems = async (data, isFromExtension) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const addListItems = async (data, isFromExtension) => {
|
export const addListItems = async (data, isFromExtension) => {
|
||||||
const localNodeAvailable = await isUsingLocal()
|
const isGateway = await isRunningGateway()
|
||||||
if(!localNodeAvailable) throw new Error('Please use your local node.')
|
if(isGateway){
|
||||||
|
throw new Error('This action cannot be done through a gateway')
|
||||||
|
}
|
||||||
const requiredFields = ["list_name", "items"];
|
const requiredFields = ["list_name", "items"];
|
||||||
const missingFields: string[] = [];
|
const missingFields: string[] = [];
|
||||||
requiredFields.forEach((field) => {
|
requiredFields.forEach((field) => {
|
||||||
@ -552,8 +583,10 @@ export const addListItems = async (data, isFromExtension) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const deleteListItems = async (data, isFromExtension) => {
|
export const deleteListItems = async (data, isFromExtension) => {
|
||||||
const localNodeAvailable = await isUsingLocal()
|
const isGateway = await isRunningGateway()
|
||||||
if(!localNodeAvailable) throw new Error('Please use your local node.')
|
if(isGateway){
|
||||||
|
throw new Error('This action cannot be done through a gateway')
|
||||||
|
}
|
||||||
const requiredFields = ["list_name", "item"];
|
const requiredFields = ["list_name", "item"];
|
||||||
const missingFields: string[] = [];
|
const missingFields: string[] = [];
|
||||||
requiredFields.forEach((field) => {
|
requiredFields.forEach((field) => {
|
||||||
@ -1431,7 +1464,7 @@ export const getUserWallet = async (data, isFromExtension) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getWalletBalance = async (data, bypassPermission?: boolean, isFromExtension) => {
|
export const getWalletBalance = async (data, bypassPermission?: boolean, isFromExtension, appInfo) => {
|
||||||
const requiredFields = ["coin"];
|
const requiredFields = ["coin"];
|
||||||
const missingFields: string[] = [];
|
const missingFields: string[] = [];
|
||||||
requiredFields.forEach((field) => {
|
requiredFields.forEach((field) => {
|
||||||
@ -1445,7 +1478,7 @@ export const getWalletBalance = async (data, bypassPermission?: boolean, isFromE
|
|||||||
throw new Error(errorMsg);
|
throw new Error(errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
const value = (await getPermission(`qAPPAutoWalletBalance-${data.coin}`)) || false;
|
const value = (await getPermission(`qAPPAutoWalletBalance-${appInfo?.name}-${data.coin}`)) || false;
|
||||||
let skip = false;
|
let skip = false;
|
||||||
if (value) {
|
if (value) {
|
||||||
skip = true;
|
skip = true;
|
||||||
@ -1465,7 +1498,7 @@ export const getWalletBalance = async (data, bypassPermission?: boolean, isFromE
|
|||||||
|
|
||||||
const { accepted = false, checkbox1 = false } = resPermission || {};
|
const { accepted = false, checkbox1 = false } = resPermission || {};
|
||||||
if(resPermission){
|
if(resPermission){
|
||||||
setPermission(`qAPPAutoWalletBalance-${data.coin}`, checkbox1);
|
setPermission(`qAPPAutoWalletBalance-${appInfo?.name}-${data.coin}`, checkbox1);
|
||||||
}
|
}
|
||||||
if (accepted || bypassPermission || skip) {
|
if (accepted || bypassPermission || skip) {
|
||||||
let coin = data.coin;
|
let coin = data.coin;
|
||||||
@ -2093,8 +2126,9 @@ export const sendCoin = async (data, isFromExtension) => {
|
|||||||
const address = wallet.address0;
|
const address = wallet.address0;
|
||||||
const resKeyPair = await getKeyPair();
|
const resKeyPair = await getKeyPair();
|
||||||
const parsedData = JSON.parse(resKeyPair);
|
const parsedData = JSON.parse(resKeyPair);
|
||||||
const localNodeAvailable = await isUsingLocal()
|
const isGateway = await isRunningGateway()
|
||||||
if(checkCoin !== 'QORT' && !localNodeAvailable) throw new Error('Cannot send a non-QORT coin through the gateway. Please use your local node.')
|
|
||||||
|
if(checkCoin !== 'QORT' && isGateway) throw new Error('Cannot send a non-QORT coin through the gateway. Please use your local node.')
|
||||||
if (checkCoin === "QORT") {
|
if (checkCoin === "QORT") {
|
||||||
// Params: data.coin, data.destinationAddress, data.amount, data.fee
|
// Params: data.coin, data.destinationAddress, data.amount, data.fee
|
||||||
// TODO: prompt user to send. If they confirm, call `POST /crosschain/:coin/send`, or for QORT, broadcast a PAYMENT transaction
|
// TODO: prompt user to send. If they confirm, call `POST /crosschain/:coin/send`, or for QORT, broadcast a PAYMENT transaction
|
||||||
@ -2790,3 +2824,59 @@ export const cancelSellOrder = async (data, isFromExtension) => {
|
|||||||
throw new Error(error?.message || "Failed to submit sell order.");
|
throw new Error(error?.message || "Failed to submit sell order.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const adminAction = async (data, isFromExtension) => {
|
||||||
|
const requiredFields = [
|
||||||
|
"type",
|
||||||
|
];
|
||||||
|
const missingFields: string[] = [];
|
||||||
|
requiredFields.forEach((field) => {
|
||||||
|
if (!data[field]) {
|
||||||
|
missingFields.push(field);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (missingFields.length > 0) {
|
||||||
|
const missingFieldsString = missingFields.join(", ");
|
||||||
|
const errorMsg = `Missing fields: ${missingFieldsString}`;
|
||||||
|
throw new Error(errorMsg);
|
||||||
|
}
|
||||||
|
const isGateway = await isRunningGateway()
|
||||||
|
if(isGateway){
|
||||||
|
throw new Error('This action cannot be done through a gateway')
|
||||||
|
}
|
||||||
|
|
||||||
|
let apiEndpoint = '';
|
||||||
|
switch (data.type.toLowerCase()) {
|
||||||
|
case 'stop':
|
||||||
|
apiEndpoint = await createEndpoint('/admin/stop');
|
||||||
|
break;
|
||||||
|
case 'restart':
|
||||||
|
apiEndpoint = await createEndpoint('/admin/restart');
|
||||||
|
break;
|
||||||
|
case 'bootstrap':
|
||||||
|
apiEndpoint = await createEndpoint('/admin/bootstrap');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown admin action type: ${data.type}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const resPermission = await getUserPermission({
|
||||||
|
text1: `Do you give this application permission to perform a node ${data.type}?`,
|
||||||
|
}, isFromExtension);
|
||||||
|
const { accepted } = resPermission;
|
||||||
|
if (accepted) {
|
||||||
|
const response = await fetch(apiEndpoint);
|
||||||
|
if (!response.ok) throw new Error("Failed to perform request");
|
||||||
|
|
||||||
|
let res;
|
||||||
|
try {
|
||||||
|
res = await response.clone().json();
|
||||||
|
} catch (e) {
|
||||||
|
res = await response.text();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
throw new Error("User declined request");
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user