[release] v0.17.0-unstable11

This commit is contained in:
Yann Stepienik
2024-10-09 23:04:11 +01:00
parent b0c181cd8d
commit f4facae52f
49 changed files with 5774 additions and 222 deletions
+2 -2
View File
@@ -36,11 +36,11 @@ jobs:
- run:
name: download Go
command: wget https://golang.org/dl/go1.21.6.linux-amd64.tar.gz
command: wget https://golang.org/dl/go1.23.2.linux-amd64.tar.gz
- run:
name: install Go
command: sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.21.6.linux-amd64.tar.gz
command: sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.23.2.linux-amd64.tar.gz
- run:
name: set Go path
+2
View File
@@ -1,4 +1,5 @@
## Version 0.17.0
- Added RClone integration to manage and mount remote storage
- Added zip and deb packages for docker-less distribution
- Added TCP/UDP socket proxying
- TCP/UDP proxying includes smart-shield protections, constellation support, geoblocking, and monitoring
@@ -11,6 +12,7 @@
- Fix bug with missing post-install instructs on service creation
- Added missing geo block events in monitoring
- Improved accessiblity of the menu for screen readers
- Update to Go 1.23.2
## Version 0.16.3
- Local domains now produce services instead of CNAME for better compatibility
+5 -2
View File
@@ -7,6 +7,7 @@ import * as _constellation from './constellation';
import * as _metrics from './metrics';
import * as _storage from './storage';
import * as _cron from './cron';
import * as _rclone from './rclone';
import * as authDemo from './authentication.demo';
import * as usersDemo from './users.demo';
@@ -221,12 +222,12 @@ let restartServer = () => {
}));
}
function terminal(containerId) {
function terminal(startCmd = "bash") {
let protocol = 'ws://';
if (window.location.protocol === 'https:') {
protocol = 'wss://';
}
return new WebSocket(protocol + window.location.host + '/cosmos/api/terminal');
return new WebSocket(protocol + window.location.host + '/cosmos/api/terminal/'+startCmd)
}
const isDemo = import.meta.env.MODE === 'demo';
@@ -240,6 +241,7 @@ let constellation = _constellation;
let metrics = _metrics;
let storage = _storage;
let cron = _cron;
let rclone = _rclone;
if(isDemo) {
auth = authDemo;
@@ -278,5 +280,6 @@ export {
storage,
terminal,
cron,
rclone,
restartServer
};
+80
View File
@@ -0,0 +1,80 @@
import {wrapRClone} from './wrap';
function _setData(data) {
if(!data) {
data = {};
}
if(!data.parameters) {
data.parameters = {};
}
data.parameters.config_is_local = false;
data.parameters.config_refresh_token = false;
return data;
}
function create(data) {
return wrapRClone(fetch('/cosmos/rclone/config/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(_setData(data))
}))
}
function list() {
return wrapRClone(fetch('/cosmos/rclone/config/dump', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({}) // Empty body for POST request
}))
}
// New function to update a provider
function update(providerId, data) {
return wrapRClone(fetch(`/cosmos/rclone/config/update/${providerId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(_setData(data))
}))
}
// New function to ping a storage
function pingStorage(remoteName) {
return wrapRClone(fetch('/cosmos/rclone/operations/about', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
"fs": remoteName + ":/",
})
}))
}
function deleteRemote(remoteName) {
return wrapRClone(fetch('/cosmos/rclone/config/delete', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: remoteName
})
}))
}
export {
create,
list,
deleteRemote,
update,
pingStorage
};
+14
View File
@@ -1,5 +1,19 @@
let snackit;
export function wrapRClone(apicall) {
return apicall.then(async (response) => {
let rep = await response.json();
if (response.status >= 400) {
snackit(rep.error);
const e = new Error(rep.error);
e.status = response.status;
e.code = response.status;
throw e;
}
return rep;
});
};
export default function wrap(apicall, noError = false) {
return apicall.then(async (response) => {
let rep;
@@ -92,7 +92,7 @@ const PrettyTableView = ({ isLoading, getKey, data, columns, sort, onRowClick, l
})
.map((row, key) => (
<TableRow
key={getKey(row)}
key={getKey(row, key)}
sx={{
cursor: 'pointer',
borderLeft: 'transparent solid 2px',
+1 -18
View File
@@ -53,24 +53,7 @@ const TerminalComponent = ({refresh, connectButtons}) => {
if (event.data === '_PONG_') {
return;
}
try {
let data;
if (event.data instanceof Blob) {
// Handle Blob data
data = await event.data.text();
} else if (event.data instanceof ArrayBuffer) {
// Handle ArrayBuffer data
data = new TextDecoder().decode(event.data);
} else {
// Assume it's already a string
data = event.data;
}
terminal.write(data);
} catch (e) {
console.error("Error processing message:", e);
}
terminal.write(event.data);
};
ws.current.onclose = () => {
@@ -25,22 +25,22 @@ const TerminalHeader = () => {
};
return isAdmin ? (<>
<IconButton
disableRipple
color="secondary"
sx={{ color: 'text.primary' }}
aria-label="open profile"
aria-haspopup="true"
onClick={onopen}
disabled={!status || status.containerized}
>
<Tooltip title={(!status || status.containerized) ?
t('mgmt.servapps.containers.terminal.disabled') :
t('mgmt.servapps.containers.terminal.enabled')
}>
<BorderOuterOutlined />
</Tooltip>
</IconButton>
<Tooltip title={(!status || status.containerized) ?
t('mgmt.servapps.containers.terminal.disabled') :
t('mgmt.servapps.containers.terminal.enabled')
}>
<IconButton
disableRipple
color="secondary"
sx={{ color: 'text.primary' }}
aria-label="open profile"
aria-haspopup="true"
onClick={onopen}
disabled={!status || status.containerized}
>
<BorderOuterOutlined />
</IconButton>
</Tooltip>
<Dialog open={open} onClose={() => setOpen(false)} maxWidth="md" fullWidth={true}>
<DialogTitle>{t('mgmt.servapps.containers.terminal.enabled')}</DialogTitle>
+34 -10
View File
@@ -16,7 +16,7 @@ import RestartModal from '../users/restart';
import { CosmosCheckbox, CosmosCollapse, CosmosFormDivider, CosmosInputText, CosmosSelect } from '../users/formShortcuts';
import { CosmosContainerPicker } from '../users/containerPicker';
import { snackit } from '../../../api/wrap';
import { ValidateRouteSchema, getHostnameFromName, sanitizeRoute } from '../../../utils/routes';
import { IsRouteSocketProxy, ValidateRouteSchema, getHostnameFromName, sanitizeRoute } from '../../../utils/routes';
import { isDomain } from '../../../utils/indexs';
import { useTranslation } from 'react-i18next';
@@ -45,11 +45,7 @@ const checkHost = debounce((host, setHostError) => {
} else {
setHostError(null);
}
}, 500)
const isHTTP = (url) => {
return url.startsWith('http://') || url.startsWith('https://');
}
}, 500);
const RouteManagement = ({ routeConfig, routeNames, config, TargetContainer, noControls = false, lockTarget = false, title, setRouteConfig, submitButton = false, newRoute }) => {
const { t } = useTranslation();
@@ -80,7 +76,7 @@ const RouteManagement = ({ routeConfig, routeNames, config, TargetContainer, noC
Name: routeConfig.Name,
Description: routeConfig.Description,
Mode: routeConfig.Mode || "SERVAPP",
Target: routeConfig.Target,
Target: routeConfig.Target || 'http://',
UseHost: routeConfig.UseHost,
Host: routeConfig.Host,
AcceptInsecureHTTPSTarget: routeConfig.AcceptInsecureHTTPSTarget === true,
@@ -116,6 +112,13 @@ const RouteManagement = ({ routeConfig, routeNames, config, TargetContainer, noC
fullValues = sanitizeRoute(fullValues);
if(IsRouteSocketProxy(fullValues)) {
if(!fullValues.Host.includes(':')) {
fullValues.Host = `localhost:${fullValues.Host}`;
}
fullValues.UseHost = true;
}
let op;
if(newRoute) {
op = API.config.newRoute(routeConfig.Name, fullValues)
@@ -156,6 +159,13 @@ const RouteManagement = ({ routeConfig, routeNames, config, TargetContainer, noC
return { Name: 'Name must be unique' }
}
if(IsRouteSocketProxy(fullValues)) {
if(!fullValues.Host.includes(':')) {
fullValues.Host = `localhost:${fullValues.Host}`;
}
fullValues.UseHost = true;
}
setRouteConfig && debounce(() => setRouteConfig(fullValues), 500)();
}}
>
@@ -239,7 +249,22 @@ const RouteManagement = ({ routeConfig, routeNames, config, TargetContainer, noC
/>}
<CosmosFormDivider title={t('global.source')} />
{IsRouteSocketProxy(formik.values) && <>
<Grid item xs={12}>
<Alert color='info'>{t('mgmt.urls.edit.sourceInfoPort')}</Alert>
</Grid>
<CosmosInputText
name="Host"
label={t('mgmt.servapps.networks.list.host-port')}
placeholder={1234}
formik={formik}
onChange={(e) => {
}}
/>
</>}
{!IsRouteSocketProxy(formik.values) && <>
<Grid item xs={12}>
<Alert color='info'>{t('mgmt.urls.edit.sourceInfo')}</Alert>
</Grid>
@@ -266,7 +291,6 @@ const RouteManagement = ({ routeConfig, routeNames, config, TargetContainer, noC
</>
)}
{isHTTP(formik.values.Target) && <>
<CosmosCheckbox
name="UsePathPrefix"
label={t('mgmt.urls.edit.usePathPrefixCheckbox.usePathPrefixLabel')}
@@ -291,7 +315,7 @@ const RouteManagement = ({ routeConfig, routeNames, config, TargetContainer, noC
<CosmosFormDivider title={t('mgmt.urls.edit.basicSecurityTitle')} />
{isHTTP(formik.values.Target) && <>
{!IsRouteSocketProxy(formik.values) && <>
<CosmosCheckbox
name="AuthEnabled"
label={t('mgmt.urls.edit.basicSecurity.authEnabledCheckbox.authEnabledLabel')}
@@ -341,7 +365,7 @@ const RouteManagement = ({ routeConfig, routeNames, config, TargetContainer, noC
formik={formik}
/>
{isHTTP(formik.values.Target) && <>
{!IsRouteSocketProxy(formik.values) && <>
<CosmosFormDivider />
<Alert severity='info'>{t('mgmt.urls.edit.advancedSettings.advancedSettingsInfo')}</Alert>
<CosmosInputText
+1 -1
View File
@@ -190,7 +190,7 @@ const ProxyManagement = () => {
{routes && <PrettyTableView
data={routes}
getKey={(r) => r.Name + r.Target + r.Mode}
getKey={(r, k) => k + r.Name + r.Target + r.Mode + (r._IsTunnel ? '_tunnel' : '')}
linkTo={(r) => r._IsTunnel ? '' : ('/cosmos-ui/config-url/' + r.Name)}
columns={[
{
-2
View File
@@ -470,8 +470,6 @@ const HomePage = () => {
let container;
const isSocketProxy = IsRouteSocketProxy(route);
console.log(route, isSocketProxy);
if (route.Mode == "SERVAPP") {
containerName = route.Target.split(':')[1].slice(2);
container = servApps.find((c) => c.Names.includes('/' + containerName));
+3 -3
View File
@@ -13,6 +13,8 @@ import { StorageDisks } from './disks';
import { StorageMerges } from './merges';
import { Parity } from './parity';
import { useTranslation } from 'react-i18next';
import RCloneConfig from './rclone/rclone_config';
import RClonePage from './rclone/rclone_config';
const StorageIndex = () => {
const { t } = useTranslation();
@@ -34,9 +36,7 @@ const StorageIndex = () => {
{
title: t('mgmt.storage.externalStorage'),
children: <div>
<Alert severity="info">
{t('mgmt.storage.externalStorageText')}
</Alert>
<RClonePage />
</div>,
path: 'external'
},
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,93 @@
import React, { useState, useEffect } from 'react';
import { Formik, Form, Field } from 'formik';
import { TextField, Select, MenuItem, FormControl, InputLabel, Button, Typography, Stack, Alert, CircularProgress } from '@mui/material';
import {ProvConfig, ProvAuth} from './rclone-providers';
import { CosmosCollapse } from '../../config/users/formShortcuts';
import * as API from '../../../api';
import PrettyTableView from '../../../components/tableView/prettyTableView';
import { useTranslation } from 'react-i18next';
import { CheckOutlined, PlusCircleOutlined, ReloadOutlined } from '@ant-design/icons';
import ResponsiveButton from '../../../components/responseiveButton';
import RCloneNewConfig from './rclone_new';
import { DeleteButton } from '../../../components/delete';
const RClonePage = () => {
const { t } = useTranslation();
const [selectedProvider, setSelectedProvider] = useState('');
const [providerOptions, setProviderOptions] = useState([]);
const [providers, setProviders] = useState([]);
const [pings, setPings] = useState({});
const [configModal, setConfigModal] = useState(null);
const refresh = () => {
API.rclone.list().then((response) => {
console.log(response);
setProviders(response);
Object.keys(response).forEach(provider => {
API.rclone.pingStorage(provider).then((ping) => {
setPings(pings => ({...pings, [provider]: {status: "OK"}}));
}).catch((err) => {
setPings(pings => ({...pings, [provider]: {status: "error", error: err}}));
});
});
});
}
useEffect(() => {
refresh();
}, []);
return (<>
{configModal && <RCloneNewConfig onClose={() => {setConfigModal(false); refresh();}} open={configModal} setOpen={setConfigModal} />}
{providers ?
<PrettyTableView
data={Object.keys(providers).map(key => ({name: key, ...providers[key]}))}
getKey={(r, k) => `${providers.Name + k}`}
buttons={[
<ResponsiveButton startIcon={<PlusCircleOutlined />} variant="contained" onClick={() => setConfigModal(true)}>{t('mgmt.storage.rclone.create')}</ResponsiveButton>,
<ResponsiveButton variant="outlined" startIcon={<ReloadOutlined />} onClick={() => {
refresh();
}}>{t('global.refresh')}</ResponsiveButton>
]}
columns={[
{
title: t('mgmt.storage.rclone.name'),
field: (r) => <>{r.name}</>,
},
{
title: t('mgmt.storage.rclone.type'),
field: (r) => r.type,
},
{
title: t('mgmt.storage.rclone.fullPath'),
field: (r) => '/cosmos-storage/' + r.name,
},
{
title: t('mgmt.storage.rclone.status'),
field: (r) => pings[r.name] ?
(pings[r.name].status === "OK" ? <CheckOutlined style={{color: "green"}}/> : <Alert severity="error">{pings[r.name].error.message}</Alert>)
: <CircularProgress />,
},
{
title: '',
field: (r) => <>
<div style={{position: 'relative'}}>
<DeleteButton onDelete={() => {
API.rclone.deleteRemote(r.name).then(() => {
refresh();
});
}} />
</div>
</>,
}
]}
/>
: <Stack spacing={2} direction="row" justifyContent="center">
<CircularProgress />
</Stack>}
</>);
};
export default RClonePage;
@@ -0,0 +1,155 @@
import React, { useState, useEffect } from 'react';
import { Formik, Form, Field } from 'formik';
import { TextField, Select, MenuItem, FormControl, InputLabel, Button, Typography, Stack, Alert, Dialog, DialogTitle, DialogContentText, DialogContent, DialogActions } from '@mui/material';
import { ProvConfig, ProvAuth } from './rclone-providers';
import { CosmosCollapse } from '../../config/users/formShortcuts';
import * as API from '../../../api';
import { LoadingButton } from '@mui/lab';
import { useTranslation } from 'react-i18next';
const RCloneNewConfig = ({ onClose }) => {
const [selectedProvider, setSelectedProvider] = useState('');
const [providerOptions, setProviderOptions] = useState([]);
const { t } = useTranslation();
useEffect(() => {
setProviderOptions(ProvConfig.map(config => ({
value: config.Name,
label: config.Name + ' - ' + config.Description
})));
}, []);
const handleProviderChange = (event) => {
setSelectedProvider(event.target.value);
};
const getSelectedProviderConfig = () => {
return ProvConfig.find(config => config.Name === selectedProvider);
};
const renderFormFields = (config, isSubmitting, setFieldValue) => {
const standardFields = [];
const advancedFields = [];
config.Options.forEach(option => {
const field = (
<Field
key={option.Name}
as={TextField}
name={option.Name}
label={option.Name}
helperText={option.Help}
fullWidth
margin="normal"
required={option.Required}
type={option.IsPassword ? 'password' : 'text'}
disabled={isSubmitting}
/>
);
if (option.Advanced) {
advancedFields.push(field);
} else {
standardFields.push(field);
}
});
return (
<>
<Alert severity="info">
Documentation for this provider can be found <a href={`https://rclone.org/${config.Name}/`} target="_blank" rel="noreferrer">here</a>
</Alert>
<Field
as={TextField}
name="named"
label="Name"
helperText="Name of the remote for easy reference"
fullWidth
margin="normal"
required
/>
{standardFields}
{ProvAuth.includes(config.Name) && (<>
<Alert severity="info">
This provider requires interactive authentication. In order to proceed do BLABLABLABLABLA
</Alert>
<Field
as={TextField}
name="token"
label="Token"
helperText="Token"
fullWidth
margin="normal"
required
/></>)}
{advancedFields.length > 0 && (
<CosmosCollapse title="Advanced Options">
{advancedFields}
</CosmosCollapse>
)}
</>
);
};
return (
<Dialog open={true} onClose={() => onClose()} fullWidth maxWidth="sm">
<DialogTitle>{t('mgmt.storage.rclone.create')}</DialogTitle>
<Formik
initialValues={{}}
onSubmit={(values, { setSubmitting }) => {
let fullValues = {};
fullValues.type = selectedProvider;
fullValues.name = values.named + "";
delete values.named;
fullValues.parameters = values;
setSubmitting(false);
API.rclone.create(fullValues).then(() => {
onClose();
}).catch((err) => {
onClose();
});
}}
>
{({ isSubmitting, setFieldValue }) => (
<Form>
<DialogContent>
<DialogContentText>
<FormControl fullWidth margin="normal">
<InputLabel>{t('mgmt.storage.rclone.select')}</InputLabel>
<Select
value={selectedProvider}
onChange={handleProviderChange}
>
{providerOptions.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
{selectedProvider && (
<Stack spacing={2}>
<Typography variant="h6" gutterBottom>
{getSelectedProviderConfig().Description}
</Typography>
{renderFormFields(getSelectedProviderConfig(), isSubmitting, setFieldValue)}
</Stack>
)}
</DialogContentText>
</DialogContent>
<DialogActions>
<LoadingButton type="submit" variant="contained" color="primary" disabled={isSubmitting} loading={isSubmitting}>
{t('global.createAction')}
</LoadingButton>
<Button onClick={() => onClose()}>{t('global.cancelAction')}</Button>
</DialogActions>
</Form>
)}
</Formik>
</Dialog>
);
};
export default RCloneNewConfig;
+9 -1
View File
@@ -738,5 +738,13 @@
"mgmt.servApps.container.terminal.reconnectButton": "إعادة الاتصال",
"mgmt.servapps.containers.terminal.disabled": "تم تعطيل محطة الخادم عند استخدام كوزموس كحاوية",
"mgmt.servapps.containers.terminal.enabled": "محطة الخادم",
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "يجب أن يبدأ عنوان URL الهدف بـ http:// أو https:// إذا كنت ترغب في استخدام الوكيل HTTP (لتطبيق ويب). في معظم الحالات هذا هو ما تريده."
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "يجب أن يبدأ عنوان URL الهدف بـ http:// أو https:// إذا كنت ترغب في استخدام الوكيل HTTP (لتطبيق ويب). في معظم الحالات هذا هو ما تريده.",
"mgmt.servapps.networks.list.host-port": "منفذ المضيف",
"mgmt.storage.rclone.name": "الاسم",
"mgmt.storage.rclone.type": "النوع",
"mgmt.storage.rclone.fullPath": "المسار الكامل",
"mgmt.storage.rclone.status": "الحالة",
"mgmt.storage.rclone.create": "إضافة جهة خارجية",
"mgmt.storage.rclone.select": "اختر التخزين الخارجي",
"mgmt.urls.edit.sourceInfoPort": "ما هو المنفذ الذي تريد الوصول إلى الهدف منه؟"
}
+9 -1
View File
@@ -738,5 +738,13 @@
"mgmt.servApps.container.terminal.reconnectButton": "重新连接",
"mgmt.servapps.containers.terminal.disabled": "使用 Cosmos 作为容器时,服务器终端已禁用",
"mgmt.servapps.containers.terminal.enabled": "服务器终端",
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "目标 URL 应以 http:// 或 https:// 开头,如果您要使用 HTTP 代理(用于 Web 应用)。大多数情况下,这是您想要的。"
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "目标 URL 应以 http:// 或 https:// 开头,如果您要使用 HTTP 代理(用于 Web 应用)。大多数情况下,这是您想要的。",
"mgmt.servapps.networks.list.host-port": "主机端口",
"mgmt.storage.rclone.name": "名称",
"mgmt.storage.rclone.type": "类型",
"mgmt.storage.rclone.fullPath": "完整路径",
"mgmt.storage.rclone.status": "状态",
"mgmt.storage.rclone.create": "添加远程",
"mgmt.storage.rclone.select": "选择外部存储",
"mgmt.urls.edit.sourceInfoPort": "您希望从哪个端口访问目标?"
}
+9 -1
View File
@@ -738,5 +738,13 @@
"mgmt.servApps.container.terminal.reconnectButton": "Erneut verbinden",
"mgmt.servapps.containers.terminal.disabled": "Server-Terminal ist deaktiviert, wenn Cosmos als Container verwendet wird",
"mgmt.servapps.containers.terminal.enabled": "Server-Terminal",
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "Die Ziel-URL sollte mit http:// oder https:// beginnen, wenn Sie den HTTP-Proxy verwenden möchten (für eine Web-App). In den meisten Fällen ist dies, was Sie möchten."
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "Die Ziel-URL sollte mit http:// oder https:// beginnen, wenn Sie den HTTP-Proxy verwenden möchten (für eine Web-App). In den meisten Fällen ist dies, was Sie möchten.",
"mgmt.servapps.networks.list.host-port": "Host-Port",
"mgmt.storage.rclone.name": "Name",
"mgmt.storage.rclone.type": "Typ",
"mgmt.storage.rclone.fullPath": "Vollständiger Pfad",
"mgmt.storage.rclone.status": "Status",
"mgmt.storage.rclone.create": "Remote hinzufügen",
"mgmt.storage.rclone.select": "Externer Speicher auswählen",
"mgmt.urls.edit.sourceInfoPort": "Welchen PORT möchten Sie verwenden, um auf Ihr Ziel zuzugreifen?"
}
@@ -738,5 +738,13 @@
"mgmt.servApps.container.terminal.reconnectButton": "Reconnecteth, all's well!",
"mgmt.servapps.containers.terminal.disabled": "Server Terminal is disabled when using Cosmos as a container, alas!",
"mgmt.servapps.containers.terminal.enabled": "Server Terminal, huzzah!",
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "The target URL should starteth with http:// or https:// if thou want to use the HTTP proxy (for a web app). In most cases it is what thou desireth, forsooth!"
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "The target URL should starteth with http:// or https:// if thou want to use the HTTP proxy (for a web app). In most cases it is what thou desireth, forsooth!",
"mgmt.servapps.networks.list.host-port": "Host Porticus",
"mgmt.storage.rclone.name": "Nameth",
"mgmt.storage.rclone.type": "Typeth",
"mgmt.storage.rclone.fullPath": "Fullest Pathway",
"mgmt.storage.rclone.status": "Statusth",
"mgmt.storage.rclone.create": "Addeth Remote",
"mgmt.storage.rclone.select": "Chooseth External Storehouse",
"mgmt.urls.edit.sourceInfoPort": "What PORT dost thou desire to accesseth thy target from?"
}
@@ -411,6 +411,7 @@
"mgmt.servapps.networks.containers": "Containers",
"mgmt.servapps.networks.list.bridge": "Bridge",
"mgmt.servapps.networks.list.host": "Host",
"mgmt.servapps.networks.list.host-port": "Host Port",
"mgmt.servapps.networks.list.macvlan": "MACVLAN",
"mgmt.servapps.networks.list.networkIpam": "IPAM gateway / mask",
"mgmt.servapps.networks.list.networkName": "Network Name",
@@ -454,6 +455,12 @@
"mgmt.servapps.viewStackButton": "View Stack",
"mgmt.servapps.volumes.list.ScopeTitle": "Scope",
"mgmt.servapps.volumes.volumeName": "Volume Name",
"mgmt.storage.rclone.name": "Name",
"mgmt.storage.rclone.type": "Type",
"mgmt.storage.rclone.fullPath": "Full Path",
"mgmt.storage.rclone.status": "Status",
"mgmt.storage.rclone.create": "Add Remote",
"mgmt.storage.rclone.select": "Select External Storage",
"mgmt.storage.available": "available",
"mgmt.storage.chown": "Change mount folder owner (optional, ex. 1000:1000)",
"mgmt.storage.configName.configNameLabel": "Config Name",
@@ -540,6 +547,7 @@
"mgmt.urls.edit.pathPrefixInputx.pathPrefixLabel": "Path Prefix",
"mgmt.urls.edit.pathPrefixInputx.pathPrefixPlaceholder": "Path Prefix",
"mgmt.urls.edit.sourceInfo": "What URL do you want to access your target from?",
"mgmt.urls.edit.sourceInfoPort": "What PORT do you want to access your target from?",
"mgmt.urls.edit.stripPathCheckbox.stripPathLabel": "Strip Path Prefix",
"mgmt.urls.edit.targetFolderPathInput.targetFolderPathLabel": "Target Folder Path",
"mgmt.urls.edit.targetSettings.targetUrlInput.targetUrlLabel": "Target URL",
+9 -1
View File
@@ -738,5 +738,13 @@
"mgmt.servApps.container.terminal.reconnectButton": "Reconectar",
"mgmt.servapps.containers.terminal.disabled": "El terminal del servidor está deshabilitado cuando se usa Cosmos como un contenedor",
"mgmt.servapps.containers.terminal.enabled": "Terminal del servidor",
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "La URL de destino debe comenzar con http:// o https:// si desea usar el proxy HTTP (para una aplicación web). En la mayoría de los casos, es lo que desea."
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "La URL de destino debe comenzar con http:// o https:// si desea usar el proxy HTTP (para una aplicación web). En la mayoría de los casos, es lo que desea.",
"mgmt.servapps.networks.list.host-port": "Puerto del Host",
"mgmt.storage.rclone.name": "Nombre",
"mgmt.storage.rclone.type": "Tipo",
"mgmt.storage.rclone.fullPath": "Ruta Completa",
"mgmt.storage.rclone.status": "Estado",
"mgmt.storage.rclone.create": "Agregar Remoto",
"mgmt.storage.rclone.select": "Seleccionar Almacenamiento Externo",
"mgmt.urls.edit.sourceInfoPort": "¿Desde qué PUERTO deseas acceder a tu destino?"
}
+9 -1
View File
@@ -738,5 +738,13 @@
"mgmt.servApps.container.terminal.reconnectButton": "Reconnecter",
"mgmt.servapps.containers.terminal.disabled": "Le terminal du serveur est désactivé lors de l'utilisation de Cosmos comme conteneur",
"mgmt.servapps.containers.terminal.enabled": "Terminal du serveur",
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "L'URL cible doit commencer par http:// ou https:// si vous souhaitez utiliser le proxy HTTP (pour une application web). Dans la plupart des cas, c'est ce que vous voulez."
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "L'URL cible doit commencer par http:// ou https:// si vous souhaitez utiliser le proxy HTTP (pour une application web). Dans la plupart des cas, c'est ce que vous voulez.",
"mgmt.servapps.networks.list.host-port": "Port hôte",
"mgmt.storage.rclone.name": "Nom",
"mgmt.storage.rclone.type": "Type",
"mgmt.storage.rclone.fullPath": "Chemin complet",
"mgmt.storage.rclone.status": "Statut",
"mgmt.storage.rclone.create": "Ajouter à distance",
"mgmt.storage.rclone.select": "Sélectionner le stockage externe",
"mgmt.urls.edit.sourceInfoPort": "Quel PORT souhaitez-vous utiliser pour accéder à votre cible ?"
}
+9 -1
View File
@@ -738,5 +738,13 @@
"mgmt.servApps.container.terminal.reconnectButton": "पुनः कनेक्ट करें",
"mgmt.servapps.containers.terminal.disabled": "जब कॉसमॉस को एक कंटेनर के रूप में उपयोग कर रहे हैं, तो सर्वर टर्मिनल निष्क्रिय होता है",
"mgmt.servapps.containers.terminal.enabled": "सर्वर टर्मिनल",
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "लक्षित URL को HTTP प्रॉक्सी का उपयोग करना हो तो http:// या https:// से शुरू होना चाहिए (एक वेब ऐप के लिए)। अधिकतर मामलों में यही उचित है।"
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "लक्षित URL को HTTP प्रॉक्सी का उपयोग करना हो तो http:// या https:// से शुरू होना चाहिए (एक वेब ऐप के लिए)। अधिकतर मामलों में यही उचित है।",
"mgmt.servapps.networks.list.host-port": "होस्ट पोर्ट",
"mgmt.storage.rclone.name": "नाम",
"mgmt.storage.rclone.type": "प्रकार",
"mgmt.storage.rclone.fullPath": "पूर्ण पथ",
"mgmt.storage.rclone.status": "स्थिति",
"mgmt.storage.rclone.create": "रिमोट जोड़ें",
"mgmt.storage.rclone.select": "बाहरी संग्रहण चुनें",
"mgmt.urls.edit.sourceInfoPort": "आप अपने लक्ष्य से किस पोर्ट पर पहुंचना चाहते हैं?"
}
+9 -1
View File
@@ -738,5 +738,13 @@
"mgmt.servApps.container.terminal.reconnectButton": "Riconnetti",
"mgmt.servapps.containers.terminal.disabled": "Il terminale del server è disabilitato quando si utilizza Cosmos come contenitore",
"mgmt.servapps.containers.terminal.enabled": "Terminale del Server",
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "L'URL di destinazione dovrebbe iniziare con http:// o https:// se si desidera utilizzare il proxy HTTP (per un'app web). Nella maggior parte dei casi, è quello che si desidera."
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "L'URL di destinazione dovrebbe iniziare con http:// o https:// se si desidera utilizzare il proxy HTTP (per un'app web). Nella maggior parte dei casi, è quello che si desidera.",
"mgmt.servapps.networks.list.host-port": "Porta Host",
"mgmt.storage.rclone.name": "Nome",
"mgmt.storage.rclone.type": "Tipo",
"mgmt.storage.rclone.fullPath": "Percorso Completo",
"mgmt.storage.rclone.status": "Stato",
"mgmt.storage.rclone.create": "Aggiungi Remoto",
"mgmt.storage.rclone.select": "Seleziona Archiviazione Esterna",
"mgmt.urls.edit.sourceInfoPort": "Da quale PORTA vuoi accedere al tuo obiettivo?"
}
+9 -1
View File
@@ -738,5 +738,13 @@
"mgmt.servApps.container.terminal.reconnectButton": "다시 연결",
"mgmt.servapps.containers.terminal.disabled": "서버 터미널은 코스모스를 컨테이너로 사용할 때 비활성화됩니다",
"mgmt.servapps.containers.terminal.enabled": "서버 터미널",
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "대상 URL은 http:// 또는 https://로 시작해야 HTTP 프록시를 사용할 수 있습니다 (웹 앱의 경우). 대부분의 경우 원하는 것이 이것입니다."
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "대상 URL은 http:// 또는 https://로 시작해야 HTTP 프록시를 사용할 수 있습니다 (웹 앱의 경우). 대부분의 경우 원하는 것이 이것입니다.",
"mgmt.servapps.networks.list.host-port": "호스트 포트",
"mgmt.storage.rclone.name": "이름",
"mgmt.storage.rclone.type": "유형",
"mgmt.storage.rclone.fullPath": "전체 경로",
"mgmt.storage.rclone.status": "상태",
"mgmt.storage.rclone.create": "원격 추가",
"mgmt.storage.rclone.select": "외부 저장소 선택",
"mgmt.urls.edit.sourceInfoPort": "대상을 액세스하고 싶은 포트는 무엇입니까?"
}
+9 -1
View File
@@ -738,5 +738,13 @@
"mgmt.servApps.container.terminal.reconnectButton": "Opnieuw verbinden",
"mgmt.servapps.containers.terminal.disabled": "De serverterminal is uitgeschakeld bij gebruik van Cosmos als een container",
"mgmt.servapps.containers.terminal.enabled": "Serverterminal",
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "De doellocatie-URL moet beginnen met http:// of https:// als u de HTTP-proxy wilt gebruiken (voor een webapp). In de meeste gevallen is dit wat u wilt."
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "De doellocatie-URL moet beginnen met http:// of https:// als u de HTTP-proxy wilt gebruiken (voor een webapp). In de meeste gevallen is dit wat u wilt.",
"mgmt.servapps.networks.list.host-port": "Hostpoort",
"mgmt.storage.rclone.name": "Naam",
"mgmt.storage.rclone.type": "Type",
"mgmt.storage.rclone.fullPath": "Volledig pad",
"mgmt.storage.rclone.status": "Status",
"mgmt.storage.rclone.create": "Externe opslag toevoegen",
"mgmt.storage.rclone.select": "Selecteer externe opslag",
"mgmt.urls.edit.sourceInfoPort": "Via welke POORT wilt u toegang tot uw doelwit verkrijgen?"
}
+9 -1
View File
@@ -738,5 +738,13 @@
"mgmt.servApps.container.terminal.reconnectButton": "Połącz ponownie",
"mgmt.servapps.containers.terminal.disabled": "Terminal serwera jest wyłączony, gdy używasz Cosmos jako kontenera",
"mgmt.servapps.containers.terminal.enabled": "Terminal serwera",
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "Docelowy URL powinien zaczynać się od http:// lub https://, jeśli chcesz używać serwera proxy HTTP (dla aplikacji internetowej). W większości przypadków to właśnie to, czego chcesz."
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "Docelowy URL powinien zaczynać się od http:// lub https://, jeśli chcesz używać serwera proxy HTTP (dla aplikacji internetowej). W większości przypadków to właśnie to, czego chcesz.",
"mgmt.servapps.networks.list.host-port": "Port hosta",
"mgmt.storage.rclone.name": "Nazwa",
"mgmt.storage.rclone.type": "Typ",
"mgmt.storage.rclone.fullPath": "Pełna ścieżka",
"mgmt.storage.rclone.status": "Status",
"mgmt.storage.rclone.create": "Dodaj zdalne",
"mgmt.storage.rclone.select": "Wybierz zewnętrzny magazyn",
"mgmt.urls.edit.sourceInfoPort": "Z jakiego PORTU chcesz uzyskać dostęp do swojego celu?"
}
+9 -1
View File
@@ -738,5 +738,13 @@
"mgmt.servApps.container.terminal.reconnectButton": "Reconectar",
"mgmt.servapps.containers.terminal.disabled": "Terminal do Servidor está desabilitado quando se usa Cosmos como um contêiner",
"mgmt.servapps.containers.terminal.enabled": "Terminal do Servidor",
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "O URL de destino deve começar com http:// ou https:// se você quiser usar o proxy HTTP (para um aplicativo web). Na maioria dos casos, é o que você quer."
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "O URL de destino deve começar com http:// ou https:// se você quiser usar o proxy HTTP (para um aplicativo web). Na maioria dos casos, é o que você quer.",
"mgmt.servapps.networks.list.host-port": "Porta do Host",
"mgmt.storage.rclone.name": "Nome",
"mgmt.storage.rclone.type": "Tipo",
"mgmt.storage.rclone.fullPath": "Caminho Completo",
"mgmt.storage.rclone.status": "Status",
"mgmt.storage.rclone.create": "Adicionar Remoto",
"mgmt.storage.rclone.select": "Selecionar Armazenamento Externo",
"mgmt.urls.edit.sourceInfoPort": "De qual PORTA você deseja acessar seu destino?"
}
+9 -1
View File
@@ -738,5 +738,13 @@
"mgmt.servApps.container.terminal.reconnectButton": "Переподключиться",
"mgmt.servapps.containers.terminal.disabled": "Терминал сервера отключен при использовании Cosmos в качестве контейнера",
"mgmt.servapps.containers.terminal.enabled": "Терминал сервера",
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "Целевой URL должен начинаться с http:// или https://, если вы хотите использовать HTTP-прокси (для веб-приложения). В большинстве случаев это именно то, что вам нужно."
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "Целевой URL должен начинаться с http:// или https://, если вы хотите использовать HTTP-прокси (для веб-приложения). В большинстве случаев это именно то, что вам нужно.",
"mgmt.servapps.networks.list.host-port": "Порт хоста",
"mgmt.storage.rclone.name": "Имя",
"mgmt.storage.rclone.type": "Тип",
"mgmt.storage.rclone.fullPath": "Полный путь",
"mgmt.storage.rclone.status": "Статус",
"mgmt.storage.rclone.create": "Добавить удаленное хранилище",
"mgmt.storage.rclone.select": "Выбрать внешнее хранилище",
"mgmt.urls.edit.sourceInfoPort": "Какой ПОРТ вы хотите использовать для доступа к вашей цели?"
}
+9 -1
View File
@@ -738,5 +738,13 @@
"mgmt.servApps.container.terminal.reconnectButton": "Yeniden Bağlan",
"mgmt.servapps.containers.terminal.disabled": "Cosmos'u bir kapsayıcı olarak kullanırken Sunucu Terminali devre dışıdır",
"mgmt.servapps.containers.terminal.enabled": "Sunucu Terminali",
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "Hedef URL'nin HTTP vekilini (bir web uygulaması için) kullanmak istiyorsanız http:// veya https:// ile başlaması gerekir. Çoğu durumda istediğiniz budur."
"mgmt.urls.edit.targetSettings.targetUrlProtocolWarning": "Hedef URL'nin HTTP vekilini (bir web uygulaması için) kullanmak istiyorsanız http:// veya https:// ile başlaması gerekir. Çoğu durumda istediğiniz budur.",
"mgmt.servapps.networks.list.host-port": "Ana bilgisayar Portu",
"mgmt.storage.rclone.name": "Ad",
"mgmt.storage.rclone.type": "Tür",
"mgmt.storage.rclone.fullPath": "Tam Yol",
"mgmt.storage.rclone.status": "Durum",
"mgmt.storage.rclone.create": "Uzaktan Ekle",
"mgmt.storage.rclone.select": "Harici Depolama Seç",
"mgmt.urls.edit.sourceInfoPort": "Hedefinize hangi PORT'tan erişmek istiyorsunuz?"
}
+39 -17
View File
@@ -87,26 +87,50 @@ export const ValidateRouteSchema = Yup.object().shape({
then: Yup.string().matches(/:[0-9]+$/, <Trans i18nKey="mgmt.config.containerPicker.targetTypeValidation.noPort" />),
}),
Host: Yup.string().when('UseHost', {
is: true,
then: Yup.string()
.required('Host is required')
.matches(/[\.|\:]/, 'Host must be full domain ([sub.]domain.com) or an IP (IPs won\'t work with Let\'s Encrypt!)')
.test('is-protocol', 'Do not add the protocol here!', (value) => {
return !value.match(/\:.*?[a-zA-Z]+/);
})
}),
Host: Yup.string()
.test('is-required', 'Host is required', function (value) {
if (this.parent.UseHost && !value) {
return false;
}
if (IsRouteSocketProxy(this.parent) && !value) {
return false;
}
return true;
})
.test('is-domain', 'Host must be full domain ([sub.]domain.com) or an IP (IPs won\'t work with Let\'s Encrypt!)', function (value) {
if (this.parent.UseHost && value && !IsRouteSocketProxy(this.parent) && !value.match(/[\.|\:]/)) {
return false;
}
return true;
})
.test('is-protocol', 'Do not add the protocol here!', function (value) {
if (this.parent.UseHost && value && value.match(/^([a-zA-Z]):\/\//)) {
return false;
}
return true;
})
.test('is-port', 'Must be a valid port', function (value) {
if (value && IsRouteSocketProxy(this.parent) && !value.match(/^(?:[a-zA-Z\-_\.]+\:)?[0-9]+$/)) {
return false;
}
return true;
}),
PathPrefix: Yup.string().when('UsePathPrefix', {
is: true,
then: Yup.string().required('Path Prefix is required').matches(/^\//, 'Path Prefix must start with / (e.g. /api). Do not include a domain/subdomain in it, use the Host for this.')
}),
UseHost: Yup.boolean().when('UsePathPrefix',
{
is: false,
then: Yup.boolean().oneOf([true], 'Source must at least be either Host or Path Prefix')
}),
UseHost: Yup.boolean().test('is-host-or-path', 'Source must be either Host or Path Prefix', function (value) {
const { UsePathPrefix, Target } = this.parent;
return (value === true || UsePathPrefix === true || IsRouteSocketProxy(Target));
}),
})
export const ValidateRoute = (routeConfig, config) => {
@@ -212,8 +236,6 @@ export const getHostnameFromName = (name, route, config, overrideOrigin) => {
}
export const IsRouteSocketProxy = (route) => {
console.log(route.Mode, route.Target)
console.log((route.Mode == "PROXY" || route.Mode == "SERVAPP") && !route.Target.startsWith('http://') && !route.Target.startsWith('https://'));
if(!route.Target || route.Target == "") return false;
return (route.Mode == "PROXY" || route.Mode == "SERVAPP") && !route.Target.startsWith('http://') && !route.Target.startsWith('https://');
}
+3 -3
View File
@@ -13,9 +13,9 @@ ENV PATH=$PATH:/usr/local/go/bin
RUN apt-get update && apt-get install -y ca-certificates openssl fdisk mergerfs snapraid && \
apt-get install -y --no-install-recommends wget curl && \
apt-get install -y --no-install-recommends nodejs && \
wget https://golang.org/dl/go1.21.6.linux-amd64.tar.gz && \
tar -C /usr/local -xzf go1.21.6.linux-amd64.tar.gz && \
rm go1.21.6.linux-amd64.tar.gz && \
wget https://golang.org/dl/go1.23.2.linux-amd64.tar.gz && \
tar -C /usr/local -xzf go1.23.2.linux-amd64.tar.gz && \
rm go1.23.2.linux-amd64.tar.gz && \
curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \
apt-get install -y nodejs && \
apt-get remove -y wget curl && \
+203 -85
View File
@@ -1,8 +1,8 @@
module github.com/azukaar/cosmos-server
go 1.21
go 1.23
toolchain go1.21.6
toolchain go1.23.2
require (
github.com/256dpi/lungo v0.3.7
@@ -18,7 +18,7 @@ require (
github.com/go-chi/chi v4.0.2+incompatible
github.com/go-chi/httprate v0.7.1
github.com/go-co-op/gocron/v2 v2.2.4
github.com/go-playground/validator/v10 v10.14.0
github.com/go-playground/validator/v10 v10.20.0
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
@@ -29,27 +29,32 @@ require (
github.com/ory/fosite v0.44.0
github.com/oschwald/geoip2-golang v1.8.0
github.com/pquerna/otp v1.4.0
github.com/shirou/gopsutil/v3 v3.23.9
github.com/shirou/gopsutil/v3 v3.24.5
github.com/sirupsen/logrus v1.9.3
go.deanishe.net/favicon v0.1.0
go.mongodb.org/mongo-driver v1.14.0
golang.org/x/crypto v0.22.0
golang.org/x/net v0.22.0
golang.org/x/sys v0.19.0
golang.org/x/crypto v0.28.0
golang.org/x/net v0.30.0
golang.org/x/sys v0.26.0
gopkg.in/yaml.v2 v2.4.0
k8s.io/utils v0.0.0-20240102154912-e7106e64919e
)
require (
cloud.google.com/go/compute v1.23.3 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
bazil.org/fuse v0.0.0-20230120002735-62a210ff1fd5 // indirect
cloud.google.com/go/auth v0.9.7 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
cloud.google.com/go/compute v1.28.0 // indirect
cloud.google.com/go/compute/metadata v0.5.2 // indirect
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.1.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.1.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/storage/azfile v1.3.1 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.29 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.22 // indirect
@@ -59,43 +64,78 @@ require (
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
github.com/Files-com/files-sdk-go/v3 v3.2.61 // indirect
github.com/Max-Sum/base32768 v0.0.0-20230304063302-18e6ce5945fd // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
github.com/PuerkitoBio/goquery v1.6.0 // indirect
github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf // indirect
github.com/ProtonMail/gluon v0.17.1-0.20230724134000-308be39be96e // indirect
github.com/ProtonMail/go-crypto v1.0.0 // indirect
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f // indirect
github.com/ProtonMail/go-srp v0.0.7 // indirect
github.com/ProtonMail/gopenpgp/v2 v2.7.5 // indirect
github.com/PuerkitoBio/goquery v1.10.0 // indirect
github.com/a8m/tree v0.0.0-20240104212747-2c8764a5f17e // indirect
github.com/aalpar/deheap v0.0.0-20210914013432-0cc84d79dec3 // indirect
github.com/abbot/go-http-auth v0.4.0 // indirect
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 // indirect
github.com/anacrolix/dms v1.7.1 // indirect
github.com/anacrolix/generics v0.0.2 // indirect
github.com/anacrolix/log v0.16.0 // indirect
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
github.com/andybalholm/cascadia v1.1.0 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/appscode/go-querystring v0.0.0-20170504095604-0126cfb3f1dc // indirect
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
github.com/aws/aws-sdk-go-v2 v1.24.1 // indirect
github.com/aws/aws-sdk-go-v2/config v1.26.6 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.16.16 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 // indirect
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aws/aws-sdk-go-v2 v1.32.1 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.6 // indirect
github.com/aws/aws-sdk-go-v2/config v1.27.42 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.40 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.16 // indirect
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.29 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.20 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.20 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.20 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.1 // indirect
github.com/aws/aws-sdk-go-v2/service/lightsail v1.34.0 // indirect
github.com/aws/aws-sdk-go-v2/service/route53 v1.37.0 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.18.7 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect
github.com/aws/smithy-go v1.19.0 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.65.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.24.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.32.1 // indirect
github.com/aws/smithy-go v1.22.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/bradenaw/juniper v0.15.3 // indirect
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect
github.com/buengese/sgzip v0.1.1 // indirect
github.com/calebcase/tmpfile v1.0.3 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/chilts/sid v0.0.0-20190607042430-660e94789ec9 // indirect
github.com/civo/civogo v0.3.11 // indirect
github.com/cloudflare/circl v1.4.0 // indirect
github.com/cloudflare/cloudflare-go v0.86.0 // indirect
github.com/cloudsoda/go-smb2 v0.0.0-20231124195312-f3ec8ae2c891 // indirect
github.com/colinmarc/hdfs/v2 v2.4.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpu/goacmedns v0.1.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/creack/pty v1.1.23 // indirect
github.com/cristalhq/jwt/v4 v4.0.2 // indirect
github.com/cronokirby/saferith v0.33.0 // indirect
github.com/dave/jennifer v1.4.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/deepmap/oapi-codegen v1.9.1 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
@@ -103,68 +143,103 @@ require (
github.com/dnsimple/dnsimple-go v1.2.0 // indirect
github.com/docker/docker-credential-helpers v0.8.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/dropbox/dropbox-sdk-go-unofficial/v6 v6.0.5 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/ecordell/optgen v0.0.6 // indirect
github.com/emersion/go-message v0.18.1 // indirect
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 // indirect
github.com/emersion/go-vcard v0.0.0-20230815062825-8fda7d206ec9 // indirect
github.com/exoscale/egoscale v0.102.3 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/flynn/noise v1.1.0 // indirect
github.com/friendsofgo/errors v0.9.2 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
github.com/gdamore/encoding v1.0.1 // indirect
github.com/gdamore/tcell/v2 v2.7.4 // indirect
github.com/geoffgarside/ber v1.1.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-chi/chi/v5 v5.1.0 // indirect
github.com/go-darwin/apfs v0.0.0-20211011131704-f84b94dbf348 // indirect
github.com/go-errors/errors v1.0.1 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-resty/resty/v2 v2.11.0 // indirect
github.com/go-resty/resty/v2 v2.15.3 // indirect
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/goccy/go-json v0.10.3 // indirect
github.com/godbus/dbus/v5 v5.0.4 // indirect
github.com/gofrs/flock v0.12.1 // indirect
github.com/gofrs/uuid v4.4.0+incompatible // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/glog v1.1.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/golang/glog v1.2.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
github.com/gophercloud/gophercloud v1.0.0 // indirect
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect
github.com/grandcat/zeroconf v1.0.0 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hanwen/go-fuse/v2 v2.6.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/mdns v1.0.5 // indirect
github.com/henrybear327/Proton-API-Bridge v1.0.0 // indirect
github.com/henrybear327/go-proton-api v1.0.0 // indirect
github.com/holoplot/go-avahi v1.0.1 // indirect
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
github.com/jcmturner/gofork v1.7.6 // indirect
github.com/jcmturner/goidentity/v6 v6.0.1 // indirect
github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
github.com/jlaffaye/ftp v0.2.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jonboulle/clockwork v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/jtolio/noiseconn v0.0.0-20231127013910-f6d9ecbf1de7 // indirect
github.com/jzelinskie/whirlpool v0.0.0-20201016144138-0675e54bb004 // indirect
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/klauspost/compress v1.17.10 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect
github.com/koofr/go-httpclient v0.0.0-20240520111329-e20f8f203988 // indirect
github.com/koofr/go-koofrclient v0.0.0-20221207135200-cbd7fc9ad6a6 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
github.com/labbsr0x/goh v1.0.1 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/linode/linodego v1.28.0 // indirect
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
github.com/liquidweb/liquidweb-go v1.6.4 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/lpar/date v1.0.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mattn/goveralls v0.0.6 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/mimuret/golang-iij-dpf v0.9.1 // indirect
@@ -172,17 +247,20 @@ require (
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/sys/mountinfo v0.7.2 // indirect
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/montanaflynn/stats v0.7.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect
github.com/nats-io/jwt/v2 v2.5.5 // indirect
github.com/nats-io/nats-server/v2 v2.10.14 // indirect
github.com/nats-io/nats.go v1.34.1 // indirect
github.com/nats-io/nkeys v0.4.7 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/ncw/swift/v2 v2.0.3 // indirect
github.com/nrdcg/auroradns v1.1.0 // indirect
github.com/nrdcg/bunny-go v0.0.0-20230728143221-c9dda82568d9 // indirect
github.com/nrdcg/desec v0.7.0 // indirect
@@ -197,88 +275,128 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect
github.com/oracle/oci-go-sdk/v65 v65.75.1 // indirect
github.com/ory/go-acc v0.2.6 // indirect
github.com/ory/go-convenience v0.1.0 // indirect
github.com/ory/viper v1.7.5 // indirect
github.com/ory/x v0.0.214 // indirect
github.com/oschwald/maxminddb-golang v1.10.0 // indirect
github.com/ovh/go-ovh v1.4.3 // indirect
github.com/panjf2000/ants/v2 v2.10.0 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pborman/uuid v1.2.0 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/pengsrc/go-shared v0.2.1-0.20190131101655-1999055a4a14 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/pkg/sftp v1.13.6 // indirect
github.com/pkg/xattr v0.4.10 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/prometheus/client_golang v1.20.4 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.60.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/putdotio/go-putio/putio v0.0.0-20200123120452-16d982cac2b8 // indirect
github.com/rasky/go-xdr v0.0.0-20170124162913-1a41d1a06c93 // indirect
github.com/rclone/gofakes3 v0.0.3-0.20240807151802-e80146f8de87 // indirect
github.com/rclone/rclone v1.68.1 // indirect
github.com/relvacode/iso8601 v1.4.0 // indirect
github.com/rfjakob/eme v1.1.2 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 // indirect
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 // indirect
github.com/sacloud/api-client-go v0.2.8 // indirect
github.com/sacloud/go-http v0.1.6 // indirect
github.com/sacloud/iaas-api-go v1.11.1 // indirect
github.com/sacloud/packages-go v0.0.9 // indirect
github.com/samber/lo v1.47.0 // indirect
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.22 // indirect
github.com/shabbyrobe/gocovmerge v0.0.0-20230507112040-c3350d9342df // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
github.com/softlayer/softlayer-go v1.1.3 // indirect
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
github.com/spf13/afero v1.9.2 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/cobra v1.1.1 // indirect
github.com/sony/gobreaker v1.0.0 // indirect
github.com/spacemonkeygo/monkit/v3 v3.0.23 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.1 // indirect
github.com/stretchr/testify v1.8.4 // indirect
github.com/subosito/gotenv v1.4.1 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.9.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/t3rm1n4l/go-mega v0.0.0-20240219080617-d494b6a8ace7 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 // indirect
github.com/tidwall/btree v1.7.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.9.0 // indirect
github.com/transip/gotransip/v6 v6.23.0 // indirect
github.com/ultradns/ultradns-go-sdk v1.6.1-20231103022937-8589b6a // indirect
github.com/unknwon/goconfig v1.0.0 // indirect
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
github.com/vultr/govultr/v2 v2.17.2 // indirect
github.com/willscott/go-nfs v0.0.3-0.20240425122109-91bc38957cc9 // indirect
github.com/willscott/go-nfs-client v0.0.0-20240104095149-b44639837b00 // indirect
github.com/winfsp/cgofuse v1.5.1-0.20221118130120-84c0898ad2e0 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f // indirect
github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997 // indirect
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
github.com/yunify/qingstor-sdk-go/v3 v3.2.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
github.com/zeebo/blake3 v0.2.4 // indirect
github.com/zeebo/errs v1.3.0 // indirect
go.etcd.io/bbolt v1.3.11 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect
go.opentelemetry.io/otel v1.30.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.30.0 // indirect
go.opentelemetry.io/otel/sdk v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.30.0 // indirect
go.uber.org/automaxprocs v1.5.3 // indirect
go.uber.org/ratelimit v0.2.0 // indirect
golang.org/x/exp v0.0.0-20231219180239-dc181d75b848 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/oauth2 v0.16.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.17.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.149.0 // indirect
goftp.io/server/v2 v2.0.1 // indirect
golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/term v0.25.0 // indirect
golang.org/x/text v0.19.0 // indirect
golang.org/x/time v0.7.0 // indirect
golang.org/x/tools v0.26.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/api v0.199.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect
google.golang.org/grpc v1.61.1 // indirect
google.golang.org/protobuf v1.32.0 // indirect
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect
google.golang.org/grpc v1.67.1 // indirect
google.golang.org/protobuf v1.35.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/ns1/ns1-go.v2 v2.7.13 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 // indirect
gopkg.in/validator.v2 v2.0.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.4.0 // indirect
k8s.io/klog/v2 v2.80.1 // indirect
moul.io/http2curl/v2 v2.3.0 // indirect
storj.io/common v0.0.0-20241001184207-4de7dfb84e22 // indirect
storj.io/drpc v0.0.35-0.20240709171858-0075ac871661 // indirect
storj.io/eventkit v0.0.0-20240415002644-1d9596fee086 // indirect
storj.io/infectious v0.0.2 // indirect
storj.io/picobuf v0.0.4 // indirect
storj.io/uplink v1.13.1 // indirect
)
+468
View File
File diff suppressed because it is too large Load Diff
+2 -25
View File
@@ -1,12 +1,12 @@
{
"name": "cosmos-server",
"version": "0.16.0-unstable26",
"version": "0.17.0-unstable10",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cosmos-server",
"version": "0.16.0-unstable26",
"version": "0.17.0-unstable10",
"dependencies": {
"@ant-design/colors": "^6.0.0",
"@ant-design/icons": "^4.7.0",
@@ -27,7 +27,6 @@
"apexcharts": "^3.35.5",
"bcryptjs": "^2.4.3",
"browserslist": "^4.21.7",
"claude-ai": "^1.2.2",
"date-fns": "^2.30.0",
"dayjs": "^1.11.10",
"dot": "^1.1.3",
@@ -5015,14 +5014,6 @@
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
},
"node_modules/claude-ai": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/claude-ai/-/claude-ai-1.2.2.tgz",
"integrity": "sha512-/4NWVJvlT5+jiFxuXq6HUxFW2bN3fyaXbL2cJNF1u5vpNE/C4WkFO2O50KqwFYeeuo4PsamUbFPx6bAdLbk9RA==",
"dependencies": {
"isomorphic-fetch": "^3.0.0"
}
},
"node_modules/cliui": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
@@ -7704,15 +7695,6 @@
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
"node_modules/isomorphic-fetch": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz",
"integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==",
"dependencies": {
"node-fetch": "^2.6.1",
"whatwg-fetch": "^3.4.1"
}
},
"node_modules/jest-diff": {
"version": "29.5.0",
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz",
@@ -10900,11 +10882,6 @@
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/whatwg-fetch": {
"version": "3.6.20",
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
"integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "cosmos-server",
"version": "0.17.0-unstable10",
"version": "0.17.0-unstable11",
"description": "",
"main": "test-server.js",
"bugs": {
+4
View File
@@ -3,6 +3,10 @@ package main
import (
// "encoding/json"
"github.com/azukaar/cosmos-server/src/utils"
_ "github.com/rclone/rclone/backend/all" // import all backends
_ "github.com/rclone/rclone/fs/operations" // import operations/* rc commands
_ "github.com/rclone/rclone/fs/sync" // import sync/*
)
func LoadConfig() utils.Config {
+4 -2
View File
@@ -398,7 +398,8 @@ func InitServer() *mux.Router {
srapi.HandleFunc("/api/favicon", GetFavicon)
srapi.HandleFunc("/api/ping", PingURL)
srapi.HandleFunc("/api/me", user.Me)
srapi.HandleFunc("/api/terminal", HostTerminalRoute)
// srapi.HandleFunc("/api/terminal", HostTerminalRoute)
srapi.HandleFunc("/api/terminal/{route}", HostTerminalRoute)
srapiAdmin := router.PathPrefix("/cosmos").Subrouter()
srapiAdmin.Use(utils.ContentTypeMiddleware("application/json"))
@@ -483,7 +484,7 @@ func InitServer() *mux.Router {
srapiAdmin.HandleFunc("/api/snapraid", storage.SNAPRaidCRUDRoute)
srapiAdmin.HandleFunc("/api/snapraid/{name}", storage.SnapRAIDEditRoute)
srapiAdmin.HandleFunc("/api/snapraid/{name}/{action}", storage.SnapRAIDRunRoute)
if utils.LoggingLevelLabels[utils.GetMainConfig().LoggingLevel] == utils.DEBUG {
debugRouter := srapiAdmin.PathPrefix("/debug").Subrouter()
debugRouter.Use(utils.AdminOnlyMiddleware)
@@ -531,6 +532,7 @@ func InitServer() *mux.Router {
uirouter.Use(utils.EnsureHostname)
}
router = proxy.BuildFromConfig(router, HTTPConfig.ProxyConfig)
router.HandleFunc("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+21 -1
View File
@@ -17,7 +17,25 @@ import (
"github.com/azukaar/cosmos-server/src/proxy"
)
func HandleCLIArgs() bool {
args := os.Args[1:]
if len(args) > 0 && args[0] == "rclone" {
args = args[1:]
storage.RunRClone(args)
return true
}
return false
}
func main() {
if HandleCLIArgs() {
return
}
docker.IsInsideContainer()
if os.Getenv("COSMOS_CONFIG_FOLDER") != "" {
@@ -75,7 +93,7 @@ func main() {
config := utils.GetMainConfig()
proxy.InitSocketShield()
if !config.NewInstall {
MigratePre013()
MigratePre014()
@@ -104,6 +122,8 @@ func main() {
constellation.Init()
utils.ProxyRClone = storage.InitRemoteStorage()
storage.InitSnapRAIDConfig()
// Has to be done last, so scheduler does not re-init
+19
View File
@@ -6,8 +6,10 @@ import (
"sync"
"strings"
"strconv"
"net/url"
"github.com/azukaar/cosmos-server/src/utils"
"github.com/azukaar/cosmos-server/src/docker"
)
var (
@@ -233,6 +235,23 @@ func InitInternalSocketProxy() {
destination = "localhost:" + targetPort
} else {
destination = route.Target
if route.Mode == "SERVAPP" && (!utils.IsInsideContainer || utils.IsHostNetwork) {
url, err := url.Parse(destination)
if err != nil {
utils.Error("Create socket Route", err)
} else {
targetHost := url.Hostname()
targetIP, err := docker.GetContainerIPByName(targetHost)
if err != nil {
utils.Error("Can't find container", err)
} else {
utils.Debug("Dockerless socket Target IP: " + targetIP)
destination = targetIP + ":" + url.Port()
}
}
}
}
portpair := PortsPair{port, destination, isHTTPProxy, route}
+19
View File
@@ -12,6 +12,25 @@ func BuildFromConfig(router *mux.Router, config utils.ProxyConfig) *mux.Router {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
})
// Proxy RClone
if utils.ProxyRClone {
data64Auth := utils.Base64Encode(utils.ProxyRCloneUser + ":" + utils.ProxyRClonePwd)
rcloneRoute := utils.ProxyRouteConfig{
Name: "RClone",
Mode: "PROXY",
UseHost: false,
Target: "http://localhost:5572",
UsePathPrefix: true,
PathPrefix: "/cosmos/rclone",
AuthEnabled: true,
AdminOnly: true,
ExtraHeaders: map[string]string{
"Authorization": "Basic " + data64Auth,
},
}
RouterGen(rcloneRoute, router, RouteTo(rcloneRoute))
}
ConstellationConfig := utils.GetMainConfig().ConstellationConfig
+6
View File
@@ -142,6 +142,12 @@ func NewProxy(targetHost string, AcceptInsecureHTTPSTarget bool, DisableHeaderHa
req.Header.Set("Host", req.URL.Host)
req.Host = req.URL.Host
}
// Extra headers
for name, value := range route.ExtraHeaders {
req.Header.Del(name)
req.Header.Set(name, value)
}
}
customTransport := &http.Transport{}
+1 -1
View File
@@ -152,7 +152,7 @@ func RouterGen(route utils.ProxyRouteConfig, router *mux.Router, destination htt
timeout := route.Timeout
if(!utils.GetMainConfig().HTTPConfig.AcceptAllInsecureHostname) {
if(!utils.GetMainConfig().HTTPConfig.AcceptAllInsecureHostname && route.UseHost) {
destination = utils.EnsureHostname(destination)
}
+99
View File
@@ -0,0 +1,99 @@
package storage
import (
"os"
"os/exec"
"io"
"bufio"
"bytes"
"github.com/rclone/rclone/cmd"
_ "github.com/rclone/rclone/backend/all" // import all backends
_ "github.com/rclone/rclone/cmd/all" // import all commands
_ "github.com/rclone/rclone/lib/plugin" // import plugins
"github.com/azukaar/cosmos-server/src/utils"
)
func RunRClone(args []string) {
cmd.Root.SetArgs(args)
cmd.Main()
}
func RunRCloneCommand(command []string) (*exec.Cmd, io.WriteCloser, *bytes.Buffer, *bytes.Buffer) {
utils.Log("[RemoteStorage] Initializing remote storage")
args := []string{"rclone"}
args = append(args, command...)
cmd := exec.Command(os.Args[0], args...)
var stdoutBuf, stderrBuf bytes.Buffer
stdin, err := cmd.StdinPipe()
if err != nil {
utils.Error("[RemoteStorage] Error creating stdin pipe", err)
return nil, nil, nil, nil
}
stdoutPipe, err := cmd.StdoutPipe()
if err != nil {
utils.Error("[RemoteStorage] Error creating stdout pipe", err)
return nil, nil, nil, nil
}
stderrPipe, err := cmd.StderrPipe()
if err != nil {
utils.Error("[RemoteStorage] Error creating stderr pipe", err)
return nil, nil, nil, nil
}
err = cmd.Start()
if err != nil {
utils.Error("[RemoteStorage] Error starting rclone command", err)
return nil, nil, nil, nil
}
go func() {
scanner := bufio.NewScanner(stdoutPipe)
for scanner.Scan() {
line := scanner.Text()
utils.Debug("[RemoteStorage] " + line)
stdoutBuf.WriteString(line + "\n")
}
}()
go func() {
scanner := bufio.NewScanner(stderrPipe)
for scanner.Scan() {
line := scanner.Text()
utils.Error("[RemoteStorage] " + line, nil)
stderrBuf.WriteString(line + "\n")
}
}()
return cmd, stdin, &stdoutBuf, &stderrBuf
}
func InitRemoteStorage() bool {
configLocation := utils.CONFIGFOLDER + "rclone.conf"
utils.ProxyRCloneUser = utils.GenerateRandomString(8)
utils.ProxyRClonePwd = utils.GenerateRandomString(16)
if _, err := os.Stat(configLocation); os.IsNotExist(err) {
utils.Log("[RemoteStorage] Creating rclone config file")
file, err := os.Create(configLocation)
if err != nil {
utils.Error("[RemoteStorage] Error creating rclone config file", err)
return false
}
file.Close()
}
utils.Log("[RemoteStorage] Initializing remote storage")
RunRCloneCommand([]string{"rcd", "--rc-user=" + utils.ProxyRCloneUser, "--rc-pass=" + utils.ProxyRClonePwd, "--config=" + configLocation, "--rc-baseurl=/cosmos/rclone"})
return true
}
+36 -11
View File
@@ -6,9 +6,12 @@ import (
"syscall"
"time"
"io"
"os"
"github.com/gorilla/mux"
"github.com/creack/pty"
"github.com/gorilla/websocket"
"github.com/azukaar/cosmos-server/src/utils"
)
@@ -40,6 +43,9 @@ func HostTerminalRoute(w http.ResponseWriter, r *http.Request) {
}
utils.Log("Attempting to attach to host terminal")
vars := mux.Vars(r)
route := vars["route"]
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
utils.Error("Failed to set websocket upgrade: ", err)
@@ -51,19 +57,33 @@ func HostTerminalRoute(w http.ResponseWriter, r *http.Request) {
ws.SetReadDeadline(time.Now().Add(timeoutDuration))
ws.SetWriteDeadline(time.Now().Add(timeoutDuration))
var c *exec.Cmd
if route == "rclone-config" {
c = exec.Command(os.Args[0], "rclone", "config")
} else if route == "bash" {
c = exec.Command("bash")
} else {
utils.Error("Invalid route: " + route, nil)
http.Error(w, "Invalid route: "+route, http.StatusBadRequest)
return
}
utils.Debug("Starting command: " + c.String())
// Create arbitrary command.
c := exec.Command("bash")
// Specify the UID
uid := uint32(1000) // Replace with the desired UID
gid := uint32(1000) // Replace with the primary GID of the user
c.SysProcAttr = &syscall.SysProcAttr{
Credential: &syscall.Credential{
Uid: uid,
Gid: gid,
},
if route == "bash" {
uid := uint32(1000) // Replace with the desired UID
gid := uint32(1000) // Replace with the primary GID of the user
c.SysProcAttr = &syscall.SysProcAttr{
Credential: &syscall.Credential{
Uid: uid,
Gid: gid,
},
}
}
// Set environment variables for better terminal emulation
@@ -80,8 +100,10 @@ func HostTerminalRoute(w http.ResponseWriter, r *http.Request) {
})
if err != nil {
return
utils.Error("Failed to start pty: ", err)
return
}
// Make sure to close the pty at the end.
defer func() { _ = ptmx.Close() }() // Best effort.
@@ -146,7 +168,8 @@ func HostTerminalRoute(w http.ResponseWriter, r *http.Request) {
}
ws.SetWriteDeadline(time.Now().Add(timeoutDuration))
ws.SetReadDeadline(time.Now().Add(timeoutDuration))
if err := ws.WriteMessage(websocket.BinaryMessage, buf[:n]); err != nil {
utils.Debug("Writing to websocket: " + string(buf[:n]))
if err := ws.WriteMessage(websocket.TextMessage, buf[:n]); err != nil {
utils.Error("Failed to write to websocket: ", err)
return
}
@@ -163,6 +186,8 @@ func HostTerminalRoute(w http.ResponseWriter, r *http.Request) {
break
}
utils.Debug("Received message: " + string(message))
ws.SetWriteDeadline(time.Now().Add(timeoutDuration))
ws.SetReadDeadline(time.Now().Add(timeoutDuration))
+3 -3
View File
@@ -84,15 +84,15 @@ func Debug(message string) {
}
func Log(message string) {
logMessage(INFO, "[INFO]", bBlue, nBlue, message)
logMessage(INFO, "[INFO ]", bBlue, nBlue, message)
}
func LogReq(message string) {
logMessage(INFO, "[REQ]", bGreen, nGreen, message)
logMessage(INFO, "[REQ ]", bGreen, nGreen, message)
}
func Warn(message string) {
logMessage(WARNING, "[WARN]", bYellow, nYellow, message)
logMessage(WARNING, "[WARN ]", bYellow, nYellow, message)
}
func Error(message string, err error) {
+16 -4
View File
@@ -79,11 +79,11 @@ type User struct {
type Config struct {
LoggingLevel LoggingLevel `required,validate:"oneof=DEBUG INFO WARNING ERROR"`
MongoDB string
Database DatabaseConfig `validate:"dive"`
Database DatabaseConfig ``
DisableUserManagement bool
NewInstall bool `validate:"boolean"`
HTTPConfig HTTPConfig `validate:"required,dive,required"`
EmailConfig EmailConfig `validate:"required,dive,required"`
HTTPConfig HTTPConfig `validate:"required"`
EmailConfig EmailConfig `validate:"required"`
DockerConfig DockerConfig
BlockedCountries []string
CountryBlacklistIsWhitelist bool
@@ -105,6 +105,7 @@ type Config struct {
CRON map[string]CRONConfig
Licence string
ServerToken string
RemoteStorage RemoteStorageConfig
}
type CRONConfig struct {
@@ -240,6 +241,7 @@ type ProxyRouteConfig struct {
Icon string `yaml:"icon,omitempty"`
TunnelVia string `yaml:"tunnel_via,omitempty"`
TunneledHost string `yaml:"tunneled_host,omitempty"`
ExtraHeaders map[string]string `yaml:"extra_headers,omitempty"`
}
type EmailConfig struct {
@@ -410,4 +412,14 @@ type AlertMetricTrack struct {
Key string
Object string
Max uint64
}
}
type LocationRemoteStorageConfig struct {
Name string
Type string
Settings map[string]string
}
type RemoteStorageConfig struct {
Remotes []LocationRemoteStorageConfig
}
+8
View File
@@ -32,6 +32,10 @@ import (
var ConfigLock sync.Mutex
var ConfigLockInternal sync.Mutex
var ProxyRClone = false
var ProxyRCloneUser = ""
var ProxyRClonePwd = ""
var BaseMainConfig Config
var MainConfig Config
var IsHTTPS = false
@@ -640,6 +644,10 @@ func GetServerPort() string {
return MainConfig.HTTPConfig.HTTPPort
}
func Base64Encode(str string) string {
return base64.StdEncoding.EncodeToString([]byte(str))
}
func ImageToBase64(path string) (string, error) {
imageFile, err := os.Open(path)
if err != nil {
+6
View File
@@ -15,6 +15,12 @@ export default defineConfig({
// target: 'https://192.168.1.170:8443',
secure: false,
ws: true,
},
'/cosmos/rclone': {
target: 'https://localhost:8443',
// target: 'https://192.168.1.170:8443',
secure: false,
ws: true,
}
}
}