[release] v0.9.0-unstable5

This commit is contained in:
Yann Stepienik 2023-07-02 14:53:14 +01:00
parent f2c495baa5
commit a6c6e2b524
18 changed files with 150 additions and 141 deletions

View file

@ -53,12 +53,14 @@ const RouteConfigPage = () => {
submitButton
routeConfig={currentRoute}
routeNames={config.HTTPConfig.ProxyConfig.Routes.map((r) => r.Name)}
config={config}
/>
},
{
title: 'Security',
children: <RouteSecurity
routeConfig={currentRoute}
config={config}
/>
},
]}/>}

View file

@ -30,7 +30,7 @@ const NewRouteCreate = ({ openNewModal, setOpenNewModal, config }) => {
const routes = config.HTTPConfig.ProxyConfig.Routes || [];
return <>
<RestartModal openModal={openRestartModal} setOpenModal={setOpenRestartModal} />
<RestartModal openModal={openRestartModal} setOpenModal={setOpenRestartModal} config={config} />
<Dialog open={openNewModal} onClose={() => setOpenNewModal(false)}>
<DialogTitle>New URL</DialogTitle>
{openNewModal && <>
@ -66,6 +66,7 @@ const NewRouteCreate = ({ openNewModal, setOpenNewModal, config }) => {
down={() => {}}
deleteRoute={() => {}}
noControls
config={config}
/>
</div>
</Stack>

View file

@ -14,11 +14,11 @@ import RestartModal from '../users/restart';
import { CosmosCheckbox, CosmosFormDivider, CosmosInputText, CosmosSelect } from '../users/formShortcuts';
import { snackit } from '../../../api/wrap';
const RouteSecurity = ({ routeConfig }) => {
const RouteSecurity = ({ routeConfig, config }) => {
const [openModal, setOpenModal] = React.useState(false);
return <div style={{ maxWidth: '1000px', width: '100%', margin: '', position: 'relative' }}>
<RestartModal openModal={openModal} setOpenModal={setOpenModal} />
<RestartModal openModal={openModal} setOpenModal={setOpenModal} config={config} />
{routeConfig && <>
<Formik

View file

@ -44,7 +44,7 @@ const checkHost = debounce((host, setHostError) => {
}
}, 500)
const RouteManagement = ({ routeConfig, routeNames, TargetContainer, noControls = false, lockTarget = false, title, setRouteConfig, submitButton = false, newRoute }) => {
const RouteManagement = ({ routeConfig, routeNames, config, TargetContainer, noControls = false, lockTarget = false, title, setRouteConfig, submitButton = false, newRoute }) => {
const [openModal, setOpenModal] = React.useState(false);
const [hostError, setHostError] = React.useState(null);
@ -55,7 +55,7 @@ const RouteManagement = ({ routeConfig, routeNames, TargetContainer, noControls
}, [])
return <div style={{ maxWidth: '1000px', width: '100%', margin: '', position: 'relative' }}>
<RestartModal openModal={openModal} setOpenModal={setOpenModal} />
<RestartModal openModal={openModal} setOpenModal={setOpenModal} config={config} />
{routeConfig && <>
<Formik

View file

@ -16,20 +16,17 @@ const info = {
}
const RouteOverview = ({ routeConfig }) => {
const [openModal, setOpenModal] = React.useState(false);
const isMobile = useMediaQuery((theme) => theme.breakpoints.down('sm'));
const [confirmDelete, setConfirmDelete] = React.useState(false);
function deleteRoute(event) {
event.stopPropagation();
API.config.deleteRoute(routeConfig.Name).then(() => {
setOpenModal(true);
window.location.href = '/cosmos-ui/config-url';
});
}
return <div style={{ maxWidth: '1000px', width: '100%'}}>
<RestartModal openModal={openModal} setOpenModal={setOpenModal} />
{routeConfig && <>
<MainCard name={routeConfig.Name} title={<div>
{routeConfig.Name} &nbsp;&nbsp;

View file

@ -37,12 +37,14 @@ import UploadButtons from '../../../components/fileUpload';
import { TwitterPicker
} from 'react-color';
import {SetPrimaryColor, SetSecondaryColor} from '../../../App';
import { LoadingButton } from '@mui/lab';
const ConfigManagement = () => {
const [config, setConfig] = React.useState(null);
const [openModal, setOpenModal] = React.useState(false);
const [uploadingBackground, setUploadingBackground] = React.useState(false);
const [saveLabel, setSaveLabel] = React.useState("Save");
function refresh() {
API.config.get().then((res) => {
@ -60,7 +62,7 @@ const ConfigManagement = () => {
refresh();
}}>Refresh</Button><br /><br />
{config && <>
<RestartModal openModal={openModal} setOpenModal={setOpenModal} />
<RestartModal openModal={openModal} setOpenModal={setOpenModal} config={config} />
<Formik
initialValues={{
MongoDB: config.MongoDB,
@ -101,75 +103,69 @@ const ConfigManagement = () => {
MongoDB: Yup.string().max(512),
LoggingLevel: Yup.string().max(255).required('Logging Level is required'),
})}
onSubmit={async (values, { setErrors, setStatus, setSubmitting }) => {
try {
let toSave = {
...config,
MongoDB: values.MongoDB,
LoggingLevel: values.LoggingLevel,
RequireMFA: values.RequireMFA,
// AutoUpdate: values.AutoUpdate,
BlockedCountries: values.GeoBlocking,
HTTPConfig: {
...config.HTTPConfig,
Hostname: values.Hostname,
GenerateMissingAuthCert: values.GenerateMissingAuthCert,
HTTPPort: values.HTTPPort,
HTTPSPort: values.HTTPSPort,
SSLEmail: values.SSLEmail,
UseWildcardCertificate: values.UseWildcardCertificate,
HTTPSCertificateMode: values.HTTPSCertificateMode,
DNSChallengeProvider: values.DNSChallengeProvider,
DNSChallengeConfig: values.DNSChallengeConfig,
ForceHTTPSCertificateRenewal: values.ForceHTTPSCertificateRenewal,
},
EmailConfig: {
...config.EmailConfig,
Enabled: values.Email_Enabled,
Host: values.Email_Host,
Port: values.Email_Port,
Username: values.Email_Username,
Password: values.Email_Password,
From: values.Email_From,
UseTLS: values.Email_UseTLS,
},
DockerConfig: {
...config.DockerConfig,
SkipPruneNetwork: values.SkipPruneNetwork,
DefaultDataPath: values.DefaultDataPath
},
HomepageConfig: {
...config.HomepageConfig,
Background: values.Background
},
ThemeConfig: {
...config.ThemeConfig,
PrimaryColor: values.PrimaryColor,
SecondaryColor: values.SecondaryColor
},
}
API.config.set(toSave).then((data) => {
if (data.status == 'error') {
setStatus({ success: false });
if (data.code == 'UL001') {
setErrors({ submit: 'Wrong nickname or password. Try again or try resetting your password' });
} else if (data.status == 'error') {
setErrors({ submit: 'Unexpected error. Try again later.' });
}
setSubmitting(false);
return;
} else {
setStatus({ success: true });
setSubmitting(false);
setOpenModal(true);
}
})
} catch (err) {
setStatus({ success: false });
setErrors({ submit: err.message });
setSubmitting(false);
setSubmitting(true);
let toSave = {
...config,
MongoDB: values.MongoDB,
LoggingLevel: values.LoggingLevel,
RequireMFA: values.RequireMFA,
// AutoUpdate: values.AutoUpdate,
BlockedCountries: values.GeoBlocking,
HTTPConfig: {
...config.HTTPConfig,
Hostname: values.Hostname,
GenerateMissingAuthCert: values.GenerateMissingAuthCert,
HTTPPort: values.HTTPPort,
HTTPSPort: values.HTTPSPort,
SSLEmail: values.SSLEmail,
UseWildcardCertificate: values.UseWildcardCertificate,
HTTPSCertificateMode: values.HTTPSCertificateMode,
DNSChallengeProvider: values.DNSChallengeProvider,
DNSChallengeConfig: values.DNSChallengeConfig,
ForceHTTPSCertificateRenewal: values.ForceHTTPSCertificateRenewal,
},
EmailConfig: {
...config.EmailConfig,
Enabled: values.Email_Enabled,
Host: values.Email_Host,
Port: values.Email_Port,
Username: values.Email_Username,
Password: values.Email_Password,
From: values.Email_From,
UseTLS: values.Email_UseTLS,
},
DockerConfig: {
...config.DockerConfig,
SkipPruneNetwork: values.SkipPruneNetwork,
DefaultDataPath: values.DefaultDataPath
},
HomepageConfig: {
...config.HomepageConfig,
Background: values.Background
},
ThemeConfig: {
...config.ThemeConfig,
PrimaryColor: values.PrimaryColor,
SecondaryColor: values.SecondaryColor
},
}
return API.config.set(toSave).then((data) => {
setOpenModal(true);
setSaveLabel("Saved!");
setTimeout(() => {
setSaveLabel("Save");
}, 3000);
}).catch((err) => {
setOpenModal(true);
setSaveLabel("Error while saving, try again.");
setTimeout(() => {
setSaveLabel("Save");
}, 3000);
});
}}
>
{(formik) => (
@ -182,19 +178,17 @@ const ConfigManagement = () => {
</Grid>
)}
<Grid item xs={12}>
<AnimateButton>
<Button
<LoadingButton
disableElevation
disabled={formik.isSubmitting}
loading={formik.isSubmitting}
fullWidth
size="large"
type="submit"
variant="contained"
color="primary"
>
Save
</Button>
</AnimateButton>
{saveLabel}
</LoadingButton>
</Grid>
</MainCard>
@ -593,19 +587,17 @@ const ConfigManagement = () => {
</Grid>
)}
<Grid item xs={12}>
<AnimateButton>
<Button
<LoadingButton
disableElevation
disabled={formik.isSubmitting}
loading={formik.isSubmitting}
fullWidth
size="large"
type="submit"
variant="contained"
color="primary"
>
Save
</Button>
</AnimateButton>
{saveLabel}
</LoadingButton>
</Grid>
</MainCard>
</Stack>

View file

@ -144,7 +144,7 @@ const ProxyManagement = () => {
</Stack>
{config && <>
<RestartModal openModal={openModal} setOpenModal={setOpenModal} />
<RestartModal openModal={openModal} setOpenModal={setOpenModal} config={config} />
<NewRouteCreate openNewModal={openNewModal} setOpenNewModal={setOpenNewModal} config={config}/>
{routes && <PrettyTableView

View file

@ -22,6 +22,7 @@ import * as API from '../../../api';
import MainCard from '../../../components/MainCard';
import IsLoggedIn from '../../../isLoggedIn';
import { useEffect, useState } from 'react';
import { isDomain } from '../../../utils/indexs';
function checkIsOnline() {
API.isOnline().then((res) => {
@ -33,11 +34,29 @@ function checkIsOnline() {
});
}
const RestartModal = ({openModal, setOpenModal}) => {
const RestartModal = ({openModal, setOpenModal, config}) => {
const [isRestarting, setIsRestarting] = useState(false);
const [warn, setWarn] = useState(false);
const needsRefresh = config && (config.HTTPConfig.HTTPSCertificateMode == "SELFSIGNED" ||
!isDomain(config.HTTPConfig.Hostname))
const isNotDomain = config && !isDomain(config.HTTPConfig.Hostname);
return <>
return config ? (needsRefresh && <>
<Dialog open={openModal} onClose={() => setOpenModal(false)}>
<DialogTitle>Refresh Page</DialogTitle>
<DialogContent>
<DialogContentText>
You need to refresh the page to apply changes. {isNotDomain && 'You are not using a domain names, the server will be offline for a few seconds to remap your docker ports.'}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={() => {
window.location.reload(true);
}}>Refresh</Button>
</DialogActions>
</Dialog>
</>)
:(<>
<Dialog open={openModal} onClose={() => setOpenModal(false)}>
<DialogTitle>{!isRestarting ? 'Restart Server?' : 'Restarting Server...'}</DialogTitle>
<DialogContent>
@ -68,7 +87,7 @@ const RestartModal = ({openModal, setOpenModal}) => {
}}>Restart</Button>
</DialogActions>}
</Dialog>
</>;
</>);
};
export default RestartModal;

View file

@ -17,21 +17,12 @@ import { Formik, useFormik } from 'formik';
import * as yup from 'yup';
const OpenIdEditModal = ({ clientId, openNewModal, setOpenNewModal, config, onSubmit }) => {
const [openRestartModal, setOpenRestartModal] = useState(false);
const [submitErrors, setSubmitErrors] = useState([]);
const [newRoute, setNewRoute] = useState(null);
function addRoute() {
return API.config.addRoute(newRoute).then((res) => {
setOpenNewModal(false);
setOpenRestartModal(true);
});
}
const clientConfig = config.OpenIDClients && Object.values(config.OpenIDClients).find((c) => c.id === clientId);
return <>
<RestartModal openModal={openRestartModal} setOpenModal={setOpenRestartModal} />
<Dialog open={openNewModal} onClose={() => setOpenNewModal(false)}>
<Formik
initialValues={{

View file

@ -64,10 +64,20 @@ const NewDockerService = ({service, refresh}) => {
service = {...service};
delete service['cosmos-installer'];
const refreshConfig = () => {
API.config.get().then((res) => {
setConfig(res.data);
});
};
React.useEffect(() => {
// refreshContainer();
refreshConfig();
}, []);
const needsRestart = service && service.services && Object.values(service.services).some((c) => {
return c.routes && c.routes.length > 0;
});
const create = () => {
setLog([
'Creating Service... ',
@ -77,18 +87,16 @@ const NewDockerService = ({service, refresh}) => {
preRef.current.scrollTop = preRef.current.scrollHeight;
if (newlog.includes('[OPERATION SUCCEEDED]')) {
setIsDone(true);
needsRestart && setOpenModal(true);
refresh && refresh();
}
});
}
const needsRestart = service && service.services && Object.values(service.services).some((c) => {
return c.routes && c.routes.length > 0;
});
return <div style={{ maxWidth: '1000px', width: '100%', margin: '', position: 'relative' }}>
<MainCard title="Create Service">
<RestartModal openModal={openModal} setOpenModal={setOpenModal} />
<RestartModal openModal={openModal} setOpenModal={setOpenModal} config={config} />
<Stack spacing={1}>
{!isDone && <LoadingButton
onClick={create}
@ -104,18 +112,6 @@ const NewDockerService = ({service, refresh}) => {
{installer && installer['post-install'] && installer['post-install'].map(m =>{
return <Alert severity={m.type}>{m.label}</Alert>
})}
{needsRestart && <Alert severity="warning">Cosmos needs to be restarted to apply changes to the URLs</Alert>}
{needsRestart &&
<Button
variant="contained"
color="primary"
fullWidth
startIcon={<SyncOutlined />}
onClick={() => {
setOpenModal(true);
}}
>Restart</Button>
}
</Stack>}
<pre style={preStyle} ref={preRef}>
{!log.length && `

View file

@ -48,7 +48,7 @@ const ContainerOverview = ({ containerInfo, config, refresh, updatesAvailable, s
return (
<div style={{ maxWidth: '1000px', width: '100%' }}>
<RestartModal openModal={openRestartModal} setOpenModal={setOpenRestartModal} />
<RestartModal openModal={openRestartModal} setOpenModal={setOpenRestartModal} config={config} />
<ExposeModal
openModal={openModal}

View file

@ -45,6 +45,7 @@ const ExposeModal = ({ openModal, setOpenModal, config, updateRoutes, container
Enabled: true,
}
}}
config={config}
routeNames={config.HTTPConfig.ProxyConfig.Routes.map((r) => r.Name)}
setRouteConfig={(_newRoute) => {
setNewRoute(sanitizeRoute(_newRoute));

View file

@ -127,7 +127,7 @@ const ServApps = () => {
}
return <div>
<RestartModal openModal={openRestartModal} setOpenModal={setOpenRestartModal} />
<RestartModal openModal={openRestartModal} setOpenModal={setOpenRestartModal} config={config} />
<ExposeModal
openModal={openModal}
setOpenModal={setOpenModal}

View file

@ -1,6 +1,6 @@
{
"name": "cosmos-server",
"version": "0.9.0-unstable4",
"version": "0.9.0-unstable5",
"description": "",
"main": "test-server.js",
"bugs": {

View file

@ -86,7 +86,7 @@ func ConfigApiPatch(w http.ResponseWriter, req *http.Request) {
}
config.HTTPConfig.ProxyConfig.Routes = routes
utils.SaveConfigTofile(config)
utils.SetBaseMainConfig(config)
//utils.NeedsRestart = true
utils.RestartHTTPServer()

View file

@ -33,13 +33,16 @@ func ConfigApiSet(w http.ResponseWriter, req *http.Request) {
// restore AuthPrivateKey and TLSKey
config := utils.ReadConfigFromFile()
request.HTTPConfig.AuthPrivateKey = config.HTTPConfig.AuthPrivateKey
request.HTTPConfig.AuthPublicKey = config.HTTPConfig.AuthPublicKey
request.HTTPConfig.TLSCert = config.HTTPConfig.TLSCert
request.HTTPConfig.TLSKey = config.HTTPConfig.TLSKey
request.NewInstall = config.NewInstall
utils.SaveConfigTofile(request)
utils.NeedsRestart = true
utils.SetBaseMainConfig(request)
utils.DisconnectDB()
authorizationserver.Init()
utils.RestartHTTPServer()
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "OK",

View file

@ -56,7 +56,7 @@ func startHTTPServer(router *mux.Router) {
}
}
func startHTTPSServer(router *mux.Router, tlsCert string, tlsKey string) {
func startHTTPSServer(router *mux.Router) {
//config := utils.GetMainConfig()
utils.IsHTTPS = true
@ -88,23 +88,29 @@ func startHTTPSServer(router *mux.Router, tlsCert string, tlsKey string) {
utils.Log("Listening to HTTP on :" + serverPortHTTP)
utils.Log("Listening to HTTPS on :" + serverPortHTTPS)
tlsConf := tlsconfig.NewServerTLSConfig(tlsconfig.TLSModeServerStrict)
/*if(config.HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"]) {
tlsConf.GetCertificate = certReloader.GetCertificateFunc()
} else {*/
cert, errCert := tls.X509KeyPair(([]byte)(tlsCert), ([]byte)(tlsKey))
if errCert != nil {
utils.Fatal("Getting Certificate pair", errCert)
}
tlsConf.Certificates = []tls.Certificate{cert}
//}
// start https server
var errServ error
for(errServ == http.ErrServerClosed || errServ == nil) {
config := utils.GetMainConfig()
HTTPConfig := config.HTTPConfig
var tlsCert = HTTPConfig.TLSCert
var tlsKey= HTTPConfig.TLSKey
tlsConf := tlsconfig.NewServerTLSConfig(tlsconfig.TLSModeServerStrict)
cert, errCert := tls.X509KeyPair(([]byte)(tlsCert), ([]byte)(tlsKey))
if errCert != nil {
config.HTTPConfig.ForceHTTPSCertificateRenewal = true
utils.SetBaseMainConfig(config)
utils.Fatal("Getting Certificate pair", errCert)
}
tlsConf.Certificates = []tls.Certificate{cert}
HTTPServer = &http.Server{
TLSConfig: tlsConf,
Addr: "0.0.0.0:" + serverPortHTTPS,
@ -205,7 +211,7 @@ func InitServer() *mux.Router {
oldDomains := baseMainConfig.HTTPConfig.TLSKeyHostsCached
falledBack := false
NeedsRefresh := baseMainConfig.HTTPConfig.ForceHTTPSCertificateRenewal || (tlsCert == "" || tlsKey == "") || !utils.HasAnyNewItem(domains, oldDomains) || !CertificateIsValid(baseMainConfig.HTTPConfig.TLSValidUntil)
NeedsRefresh := baseMainConfig.HTTPConfig.ForceHTTPSCertificateRenewal || (tlsCert == "" || tlsKey == "") || utils.HasAnyNewItem(domains, oldDomains) || !CertificateIsValid(baseMainConfig.HTTPConfig.TLSValidUntil)
// If we have a certificate, we can fallback to it if necessary
CanFallback := tlsCert != "" && tlsKey != "" &&
@ -399,7 +405,7 @@ func StartServer() {
HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"]) &&
tlsCert != "" && tlsKey != "") {
utils.Log("TLS certificate exist, starting HTTPS servers and redirecting HTTP to HTTPS")
startHTTPSServer(router, tlsCert, tlsKey)
startHTTPSServer(router)
} else {
utils.Log("TLS certificates do not exists or are disabled, starting HTTP server only")
startHTTPServer(router)

View file

@ -43,10 +43,11 @@ func DB() error {
return nil
}
func Disconnect() {
func DisconnectDB() {
if err := client.Disconnect(context.TODO()); err != nil {
Fatal("DB", err)
}
client = nil
}
func GetCollection(applicationId string, collection string) (*mongo.Collection, error) {