[release] version 0.5.0-unstable20

This commit is contained in:
Yann Stepienik 2023-05-16 22:51:19 +01:00
parent 4beede621b
commit 0f46cff353
3 changed files with 181 additions and 107 deletions

View file

@ -2,7 +2,7 @@ import { useParams } from "react-router";
import Back from "../../components/back"; import Back from "../../components/back";
import { Alert, Box, CircularProgress, Grid, Stack, useTheme } from "@mui/material"; import { Alert, Box, CircularProgress, Grid, Stack, useTheme } from "@mui/material";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import * as API from "../../api"; import * as API from "../../api";
import wallpaper from '../../assets/images/wallpaper.jpg'; import wallpaper from '../../assets/images/wallpaper.jpg';
import Grid2 from "@mui/material/Unstable_Grid2/Grid2"; import Grid2 from "@mui/material/Unstable_Grid2/Grid2";
import { getFaviconURL } from "../../utils/routes"; import { getFaviconURL } from "../../utils/routes";
@ -14,14 +14,14 @@ import IsLoggedIn from "../../isLoggedIn";
const HomeBackground = () => { const HomeBackground = () => {
const theme = useTheme(); const theme = useTheme();
return ( return (
<Box sx={{ position: 'fixed', float: 'left', overflow: 'hidden', zIndex: 0, top: 0, left: 0, right: 0, bottom: 0 }}> <Box sx={{ position: 'fixed', float: 'left', overflow: 'hidden', zIndex: 0, top: 0, left: 0, right: 0, bottom: 0 }}>
<img src={wallpaper} style={{ display:'inline'}} alt="Cosmos" width="100%" height="100%" /> <img src={wallpaper} style={{ display: 'inline' }} alt="Cosmos" width="100%" height="100%" />
</Box> </Box>
); );
}; };
const blockStyle = { const blockStyle = {
margin: 0, margin: 0,
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
overflow: 'hidden', overflow: 'hidden',
textOverflow: 'ellipsis', textOverflow: 'ellipsis',
@ -30,35 +30,40 @@ const blockStyle = {
} }
const HomePage = () => { const HomePage = () => {
const { routeName } = useParams(); const { routeName } = useParams();
const [config, setConfig] = useState(null); const [serveApps, setServeApps] = useState([]);
const [coStatus, setCoStatus] = useState(null); const [config, setConfig] = useState(null);
const [coStatus, setCoStatus] = useState(null);
const [containers, setContainers] = useState(null);
const refreshStatus = () => { const refreshStatus = () => {
API.getStatus().then((res) => { API.getStatus().then((res) => {
setCoStatus(res.data); setCoStatus(res.data);
}); });
} }
const refreshConfig = () => { const refreshConfig = () => {
API.config.get().then((res) => { API.docker.list().then((res) => {
setConfig(res.data); setServeApps(res.data);
}); });
}; API.config.get().then((res) => {
setConfig(res.data);
let routes = config && (config.HTTPConfig.ProxyConfig.Routes || []); });
};
useEffect(() => { let routes = config && (config.HTTPConfig.ProxyConfig.Routes || []);
refreshConfig();
refreshStatus();
}, []);
return <Stack spacing={2} > useEffect(() => {
<IsLoggedIn /> refreshConfig();
<HomeBackground /> refreshStatus();
<style> }, []);
{`header {
return <Stack spacing={2} >
<IsLoggedIn />
<HomeBackground />
<style>
{`header {
background: rgba(0.2,0.2,0.2,0.2) !important; background: rgba(0.2,0.2,0.2,0.2) !important;
border-bottom-color: rgba(0.4,0.4,0.4,0.4) !important; border-bottom-color: rgba(0.4,0.4,0.4,0.4) !important;
color: white !important; color: white !important;
@ -84,81 +89,91 @@ const HomePage = () => {
transform: scale(1.05); transform: scale(1.05);
} }
`} `}
</style> </style>
<Stack style={{zIndex: 2}} spacing={1}> <Stack style={{ zIndex: 2 }} spacing={1}>
{coStatus && !coStatus.database && ( {coStatus && !coStatus.database && (
<Alert severity="error"> <Alert severity="error">
No Database is setup for Cosmos! User Management and Authentication will not work.<br /> No Database is setup for Cosmos! User Management and Authentication will not work.<br />
You can either setup the database, or disable user management in the configuration panel.<br /> You can either setup the database, or disable user management in the configuration panel.<br />
</Alert> </Alert>
)} )}
{coStatus && coStatus.letsencrypt && ( {coStatus && coStatus.letsencrypt && (
<Alert severity="error"> <Alert severity="error">
You have enabled Let's Encrypt for automatic HTTPS Certificate. You need to provide the configuration with an email address to use for Let's Encrypt in the configs. You have enabled Let's Encrypt for automatic HTTPS Certificate. You need to provide the configuration with an email address to use for Let's Encrypt in the configs.
</Alert> </Alert>
)} )}
{coStatus && coStatus.newVersionAvailable && ( {coStatus && coStatus.newVersionAvailable && (
<Alert severity="warning"> <Alert severity="warning">
A new version of Cosmos is available! Please update to the latest version to get the latest features and bug fixes. A new version of Cosmos is available! Please update to the latest version to get the latest features and bug fixes.
</Alert> </Alert>
)} )}
{coStatus && coStatus.needsRestart && ( {coStatus && coStatus.needsRestart && (
<Alert severity="warning"> <Alert severity="warning">
You have made changes to the configuration that require a restart to take effect. Please restart Cosmos to apply the changes. You have made changes to the configuration that require a restart to take effect. Please restart Cosmos to apply the changes.
</Alert> </Alert>
)} )}
{coStatus && coStatus.domain && ( {coStatus && coStatus.domain && (
<Alert severity="error"> <Alert severity="error">
You are using localhost or 0.0.0.0 as a hostname in the configuration. It is recommended that you use a domain name instead. You are using localhost or 0.0.0.0 as a hostname in the configuration. It is recommended that you use a domain name instead.
</Alert> </Alert>
)} )}
{coStatus && !coStatus.docker && ( {coStatus && !coStatus.docker && (
<Alert severity="error"> <Alert severity="error">
Docker is not connected! Please check your docker connection.<br/> Docker is not connected! Please check your docker connection.<br />
Did you forget to add <pre>-v /var/run/docker.sock:/var/run/docker.sock</pre> to your docker run command?<br /> Did you forget to add <pre>-v /var/run/docker.sock:/var/run/docker.sock</pre> to your docker run command?<br />
if your docker daemon is running somewhere else, please add <pre>-e DOCKER_HOST=...</pre> to your docker run command. if your docker daemon is running somewhere else, please add <pre>-e DOCKER_HOST=...</pre> to your docker run command.
</Alert> </Alert>
)} )}
</Stack> </Stack>
<Grid2 container spacing={2} style={{zIndex: 2}}> <Grid2 container spacing={2} style={{ zIndex: 2 }}>
{config && config.HTTPConfig.ProxyConfig.Routes.map((route) => { {config && serveApps && config.HTTPConfig.ProxyConfig.Routes.map((route) => {
return <Grid2 item xs={12} sm={6} md={4} lg={3} xl={3} xxl={2} key={route.Name}> let skip = false;
<Box className='app' style={{padding: 10, color: 'white', background: 'rgba(0,0,0,0.35)', borderRadius: 5}}> if(route.Mode == "SERVAPP") {
<Link to={getFullOrigin(route)} target="_blank" style={{textDecoration: 'none', color: 'white'}}> const containerName = route.Target.split(':')[1].slice(2);
console.log('try ' + containerName)
const container = serveApps.find((c) => c.Names.includes('/' + containerName));
console.log('found ' + container)
if(container && container.State != "running") {
skip = true
}
}
return !skip && <Grid2 item xs={12} sm={6} md={4} lg={3} xl={3} xxl={2} key={route.Name}>
<Box className='app' style={{ padding: 10, color: 'white', background: 'rgba(0,0,0,0.35)', borderRadius: 5 }}>
<Link to={getFullOrigin(route)} target="_blank" style={{ textDecoration: 'none', color: 'white' }}>
<Stack direction="row" spacing={2} alignItems="center">
<img src={getFaviconURL(route)} width="64px" />
<div style={{ width: '100%' }}>
<h3 style={blockStyle}>{route.Name}</h3>
<p style={blockStyle}>{route.Description}</p>
<p style={blockStyle}>{route.Target}</p>
</div>
</Stack>
</Link>
</Box>
</Grid2>
})}
{config && config.HTTPConfig.ProxyConfig.Routes.length === 0 && (
<Grid2 item xs={12} sm={12} md={12} lg={12} xl={12}>
<Box style={{ padding: 10, color: 'white', background: 'rgba(0,0,0,0.35)', borderRadius: 5 }}>
<Stack direction="row" spacing={2} alignItems="center"> <Stack direction="row" spacing={2} alignItems="center">
<img src={getFaviconURL(route)} width="64px" /> <div style={{ width: '100%' }}>
<h3 style={blockStyle}>No Apps</h3>
<div style={{width: '100%'}}> <p style={blockStyle}>You have no apps configured. Please add some apps in the configuration panel.</p>
<h3 style={blockStyle}>{route.Name}</h3>
<p style={blockStyle}>{route.Description}</p>
<p style={blockStyle}>{route.Target}</p>
</div> </div>
</Stack> </Stack>
</Link> </Box>
</Box> </Grid2>
</Grid2> )}
})} </Grid2>
</Stack>
{config && config.HTTPConfig.ProxyConfig.Routes.length === 0 && (
<Grid2 item xs={12} sm={12} md={12} lg={12} xl={12}>
<Box style={{padding: 10, color: 'white', background: 'rgba(0,0,0,0.35)', borderRadius: 5}}>
<Stack direction="row" spacing={2} alignItems="center">
<div style={{width: '100%'}}>
<h3 style={blockStyle}>No Apps</h3>
<p style={blockStyle}>You have no apps configured. Please add some apps in the configuration panel.</p>
</div>
</Stack>
</Box>
</Grid2>
)}
</Grid2>
</Stack>
} }
export default HomePage; export default HomePage;

View file

@ -1,6 +1,6 @@
{ {
"name": "cosmos-server", "name": "cosmos-server",
"version": "0.5.0-unstable19", "version": "0.5.0-unstable20",
"description": "", "description": "",
"main": "test-server.js", "main": "test-server.js",
"bugs": { "bugs": {

View file

@ -8,6 +8,7 @@ import (
"os" "os"
"io/ioutil" "io/ioutil"
"regexp" "regexp"
"path"
"encoding/json" "encoding/json"
"github.com/azukaar/cosmos-server/src/utils" "github.com/azukaar/cosmos-server/src/utils"
@ -21,22 +22,67 @@ type CachedImage struct {
var cache = make(map[string]CachedImage) var cache = make(map[string]CachedImage)
func ExtractFaviconMetaTag(html string) string { func ExtractFaviconMetaTag(filename string) string {
// Read the contents of the file
htmlBytes, err := ioutil.ReadFile(filename)
if err != nil {
return "/favicon.ico"
}
html := string(htmlBytes)
// Regular expression pattern to match the favicon metatag // Regular expression pattern to match the favicon metatag
pattern := `<link[^>]*rel="icon"[^>]*href="([^"]+)"[^>]*>` pattern := `<link[^>]*rel="icon"[^>]*(?:sizes="([^"]+)")?[^>]*href="([^"]+)"[^>]*>|<meta[^>]*name="msapplication-TileImage"[^>]*content="([^"]+)"[^>]*>`
// Compile the regular expression pattern // Compile the regular expression pattern
regex := regexp.MustCompile(pattern) regex := regexp.MustCompile(pattern)
// Find the first match in the HTML string // Find all matches in the HTML string
match := regex.FindStringSubmatch(html) matches := regex.FindAllStringSubmatch(html, -1)
if len(match) > 1 { var faviconURL string
// Extract the URL from the matched metatag
faviconURL := match[1] // Iterate over the matches to find the appropriate favicon
for _, match := range matches {
sizes := match[1]
href := match[2]
msAppTileImage := match[3]
// Check if the meta tag specifies msapplication-TileImage
if msAppTileImage != "" {
faviconURL = msAppTileImage
break
}
// Check if the sizes attribute contains 96x96
if strings.Contains(sizes, "96x96") {
faviconURL = href
break
}
// Check if the sizes attribute contains 64x64
if strings.Contains(sizes, "64x64") {
faviconURL = href
continue
}
// Check if the sizes attribute contains 32x32
if strings.Contains(sizes, "32x32") {
faviconURL = href
continue
}
// If no sizes specified, set faviconURL to the first match without sizes
if faviconURL == "" && sizes == "" {
faviconURL = href
}
}
// If a favicon URL is found, return it
if faviconURL != "" {
return faviconURL return faviconURL
} }
// Return an error if no favicon URL is found
return "/favicon.ico" return "/favicon.ico"
} }
@ -119,10 +165,23 @@ func GetFavicon(w http.ResponseWriter, req *http.Request) {
sendFallback(w) sendFallback(w)
return return
} }
if !strings.HasPrefix(faviconURL, "/") {
faviconURL = "/" + faviconURL if strings.HasPrefix(faviconURL, ".") {
// Relative URL starting with "."
// Resolve the relative URL based on the base URL
baseURL := u.Scheme + "://" + u.Host
faviconURL = baseURL + faviconURL[1:]
} else if strings.HasPrefix(faviconURL, "/") {
// Relative URL starting with "/"
// Append the relative URL to the base URL
faviconURL = u.Scheme + "://" + u.Host + faviconURL
} else {
// Relative URL without starting dot or slash
// Construct the absolute URL based on the current page's URL path
baseURL := u.Scheme + "://" + u.Host
baseURLPath := path.Dir(u.Path)
faviconURL = baseURL + baseURLPath + "/" + faviconURL
} }
faviconURL = u.Scheme + "://" + u.Host + faviconURL
} }
utils.Log("Favicon: " + faviconURL) utils.Log("Favicon: " + faviconURL)