[release] v0.17.0-unstable29

This commit is contained in:
Yann Stepienik
2024-12-15 14:13:34 +00:00
parent 0ed7d457c3
commit 68a0dd1200
11 changed files with 100 additions and 38 deletions
+4
View File
@@ -9,6 +9,8 @@
- Added log file in the config folder and a download button in the config page
- Fixed bug where lighthouses would not consider the home server as lighthouse in Constellation
- Improved terminal with better UI and keep alive in the Websocket for (to prevent timeouts during long operations)
- Fixed bug with duplicated CORS headers
- Disabled CORS for routes that have hardening disabled
- Improve logs screen for containers (better colors, fix scrolling, auto-refresh, ...)
- Fix bug with missing post-install instructs on service creation
- Added missing geo block events in monitoring
@@ -19,6 +21,8 @@
- Fix 2-parity on Snapraid
- Fix mount/unmount request false error
- Added safeguard to prevent Docker from destroying stack containers hostnames
- Added hostname to some events for visibility (Thanks @InterN0te)
- Added missing content type in OAuth (Thanks @RaidMax)
## Version 0.16.3
- Local domains now produce services instead of CNAME for better compatibility
+10 -2
View File
@@ -12,13 +12,14 @@ export const getStatus = () => {
"database": true,
"docker": true,
"domain": false,
"Licence": "true",
"Licence": true,
"hostmode": "true",
"homepage": {
"Background": "/cosmos/api/background/avif",
"Widgets": null,
"Expanded": false
},
"LicenceNumber": 9,
"hostname": "yann-server.com",
"letsencrypt": false,
"needsRestart": false,
@@ -88,4 +89,11 @@ export const uploadImage = (file) => {
"data": ""
})}, 100 );
});
}
}
export const terminal = () => ({
send: (data) => {
onmessage("This is a demo, what did you expect?");
},
close: ()=>{}
});
@@ -86,7 +86,7 @@ const RCloneNewConfig = ({ onClose, initialValues }) => {
{standardFields}
{ProvAuth.includes(config.Name) && (<>
<Alert severity="info">
{t('mgmt.storage.rclone.tokenInfo')}&nbsp;<a href={`https://cosmos-cloud.io/doc/81%20Storage/#remote-storage`} target="_blank" rel="noreferrer">link</a>
{t('mgmt.storage.rclone.tokenInfo')}&nbsp;<a href={`https://cosmos-cloud.io/doc/82%20Remote%20Storage`} target="_blank" rel="noreferrer">link</a>
</Alert>
<Field
as={TextField}
+72 -2
View File
@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
import {
Button,
Card,
Stack,
CardContent,
CardHeader,
Switch,
@@ -29,6 +30,7 @@ const PremiumSalesPage = ({salesKey, extra}) => {
const [isYearly, setIsYearly] = useState(true);
const { t, i18n } = useTranslation();
const currency = getCurrencyFromLanguage();
const currencyCode = {
"USD": "$",
"EUR": "€",
@@ -47,18 +49,27 @@ const PremiumSalesPage = ({salesKey, extra}) => {
"GBP": 88.00
}
const lifePrices = {
"USD": 249.00,
"EUR": 229.00,
"GBP": 199.00
}
const monthlyPrice = monthlyPrices[currency];
const yearlyPrice = yearlyPrices[currency];
const lifePrice = lifePrices[currency];
const discountedMonthlyPrice = (monthlyPrice * 0.85).toFixed(2);
const discountedYearlyPrice = (yearlyPrice * 0.85).toFixed(2);
const discountedLifePrice = (lifePrice * 0.85).toFixed(2);
const monthlyLink = "https://buy.stripe.com/5kAbMN4qrbkVcBGcMR?prefilled_promo_code=EARLY15";
const yearlyLink = "https://buy.stripe.com/cN2bMN9KLbkV59e9AE?prefilled_promo_code=EARLY15";
const lifeLink = "https://buy.stripe.com/8wM1896yz74F59e6ov?prefilled_promo_code=LIFE15";
const featureKeys = Array.from({ length: 6 }, (_, i) => `mgmt.sales.${salesKey}.features.${i}`);
const planFeatureKeys = Array.from({ length: 4 }, (_, i) => `mgmt.sales.plan_features.${i}`);
const planFeatureKeys = Array.from({ length: 5 }, (_, i) => `mgmt.sales.plan_features.${i}`);
return (
<Container maxWidth="md">
@@ -107,7 +118,8 @@ const PremiumSalesPage = ({salesKey, extra}) => {
<Typography>{t('mgmt.sales.yearly')}</Typography>
</Box>
<Card variant="outlined" sx={{ maxWidth: 400, margin: 'auto' }}>
<Stack spacing={2} direction="row" justifyContent="center" alignItems="center">
<Card variant="outlined" sx={{ width: 400, margin: 'auto' }}>
<CardHeader
title={<Typography variant="h4" align="center">{t(isYearly ? 'mgmt.sales.yearly_plan' : 'mgmt.sales.monthly_plan')}</Typography>}
/>
@@ -142,12 +154,70 @@ const PremiumSalesPage = ({salesKey, extra}) => {
/>
</ListItem>
))}
<ListItem key={"last"}>
<ListItemIcon>
<CheckIcon color="primary" />
</ListItemIcon>
<ListItemText
primary={t('mgmt.sales.subs_pro')}
/>
</ListItem>
</List>
<Button variant="contained" color="primary" target='_blank' fullWidth href={isYearly ? yearlyLink : monthlyLink}>
{t('mgmt.sales.upgrade_button')}
</Button>
</CardContent>
</Card>
<Card variant="outlined" sx={{ width: 400, margin: 'auto' }}>
<CardHeader
title={<Typography variant="h4" align="center">{t('mgmt.sales.life_plan')}</Typography>}
/>
<CardContent>
<Box textAlign="center" mb={2}>
<Typography variant="h3" style={{ textDecoration: 'line-through', color: 'text.secondary' }}>
{currencyCode} {lifePrice.toFixed(2)}
</Typography>
<Typography variant="h3" color="primary">
{currencyCode} {discountedLifePrice}
</Typography>
<Typography variant="body2" color="text.secondary">
-
</Typography>
<Chip
label={t('mgmt.sales.discount_chip')}
color="secondary"
sx={{ mt: 1 }}
/>
<Typography variant="body2" color="text.secondary" mt={1}>
{t('mgmt.sales.early_adopter_offer2')}
</Typography>
</Box>
<List>
{planFeatureKeys.map((key, index) => (
<ListItem key={index}>
<ListItemIcon>
<CheckIcon color="primary" />
</ListItemIcon>
<ListItemText
primary={t(key)}
/>
</ListItem>
))}
<ListItem key={"last"}>
<ListItemIcon>
<CheckIcon color="primary" />
</ListItemIcon>
<ListItemText
primary={t('mgmt.sales.life_pro')}
/>
</ListItem>
</List>
<Button variant="contained" color="primary" target='_blank' fullWidth href={lifeLink}>
{t('mgmt.sales.upgrade_button')}
</Button>
</CardContent>
</Card>
</Stack>
</Container>
);
};
+5 -1
View File
@@ -772,17 +772,21 @@
"mgmt.sales.support": "Support the ongoing development of new features and improvements of Cosmos",
"mgmt.sales.monthly": "Monthly",
"mgmt.sales.yearly": "Yearly",
"mgmt.sales.life_plan": "Lifetime Plan",
"mgmt.sales.monthly_plan": "Monthly Plan",
"mgmt.sales.yearly_plan": "Yearly Plan",
"mgmt.sales.per_month": "per month",
"mgmt.sales.per_year": "per year",
"mgmt.sales.discount_chip": "EARLY15: 15% OFF FOR LIFE",
"mgmt.sales.early_adopter_offer": "Limited time offer until February 2025 for early adopters!",
"mgmt.sales.early_adopter_offer2": "Limited time offer until April 2025 for early adopters!",
"mgmt.sales.plan_features.0": "All VPN features (unlimited)",
"mgmt.sales.plan_features.1": "Remote Storage Management",
"mgmt.sales.plan_features.2": "Network Shares Management",
"mgmt.sales.plan_features.3": "Backup Files and Containers",
"mgmt.sales.plan_features.4": "15% lifetime discount applied",
"mgmt.sales.plan_features.4": "Up to 9 users",
"mgmt.sales.yearly_savings": "Save 17% compared to monthly",
"mgmt.sales.subs_pro": "Flexible subscription",
"mgmt.sales.life_pro": "All features for life",
"mgmt.sales.upgrade_button": "Upgrade Now"
}
+1 -20
View File
@@ -5027,25 +5027,6 @@
"resolved": "https://registry.npmjs.org/can-use-dom/-/can-use-dom-0.1.0.tgz",
"integrity": "sha512-ceOhN1DL7Y4O6M0j9ICgmTYziV89WMd96SvSl0REd8PMgrY0B/WBOPoed5S1KUmJqXgUXh8gzSe6E3ae27upsQ=="
},
"node_modules/caniuse-lite": {
"version": "1.0.30001494",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001494.tgz",
"integrity": "sha512-sY2B5Qyl46ZzfYDegrl8GBCzdawSLT4ThM9b9F+aDYUrAG2zCOyMbd2Tq34mS1g4ZKBfjRlzOohQMxx28x6wJg==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
]
},
"node_modules/chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -11459,4 +11440,4 @@
}
}
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "cosmos-server",
"version": "0.17.0-unstable28",
"version": "0.17.0-unstable29",
"description": "",
"main": "test-server.js",
"bugs": {
-2
View File
@@ -5,7 +5,6 @@
<!-- sponsors -->
<h3 align="center">Thanks to the sponsors:</h3></br>
<p align="center"><a href="https://github.com/soldier1"><img src="https://avatars.githubusercontent.com/soldier1" style="border-radius:48px" width="48" height="48" alt="null" title="null" /></a>
<a href="https://github.com/DGAzr"><img src="https://avatars.githubusercontent.com/DGAzr" style="border-radius:48px" width="48" height="48" alt="null" title="null" /></a>
<a href="https://github.com/Fortcraft"><img src="https://avatars.githubusercontent.com/Fortcraft" style="border-radius:48px" width="48" height="48" alt="null" title="null" /></a>
<a href="https://github.com/Gordi90"><img src="https://avatars.githubusercontent.com/Gordi90" style="border-radius:48px" width="48" height="48" alt="Dér Kristóf Gordon" title="Dér Kristóf Gordon" /></a>
<a href="https://github.com/lilkidsuave"><img src="https://avatars.githubusercontent.com/lilkidsuave" style="border-radius:48px" width="48" height="48" alt="null" title="null" /></a>
@@ -13,7 +12,6 @@
<a href="https://github.com/AstroMando"><img src="https://avatars.githubusercontent.com/AstroMando" style="border-radius:48px" width="48" height="48" alt="null" title="null" /></a>
<a href="https://github.com/riczescaran"><img src="https://avatars.githubusercontent.com/riczescaran" style="border-radius:48px" width="48" height="48" alt="Ricardo Escaran" title="Ricardo Escaran" /></a>
<a href="https://github.com/AKAHackoon"><img src="https://avatars.githubusercontent.com/AKAHackoon" style="border-radius:48px" width="48" height="48" alt="null" title="null" /></a>
<a href="https://github.com/madejackson"><img src="https://avatars.githubusercontent.com/madejackson" style="border-radius:48px" width="48" height="48" alt="null" title="null" /></a>
<a href="https://github.com/factorten"><img src="https://avatars.githubusercontent.com/factorten" style="border-radius:48px" width="48" height="48" alt="Carr" title="Carr" /></a>
</p><!-- /sponsors -->
+3 -6
View File
@@ -53,7 +53,7 @@ func joinURLPath(a, b *url.URL) (path, rawpath string) {
// NewProxy takes target host and creates a reverse proxy
func NewProxy(targetHost string, AcceptInsecureHTTPSTarget bool, DisableHeaderHardening bool, CORSOrigin string, route utils.ProxyRouteConfig) (*httputil.ReverseProxy, error) {
func NewProxy(targetHost string, AcceptInsecureHTTPSTarget bool, DisableHeaderHardening bool, route utils.ProxyRouteConfig) (*httputil.ReverseProxy, error) {
var transport http.RoundTripper
var targetURL *url.URL
var err error
@@ -198,12 +198,9 @@ func NewProxy(targetHost string, AcceptInsecureHTTPSTarget bool, DisableHeaderHa
utils.Debug("Response from backend: " + resp.Status)
utils.Debug("URL was " + resp.Request.URL.String())
if CORSOrigin != "" {
if !DisableHeaderHardening {
resp.Header.Del("Access-Control-Allow-Origin")
resp.Header.Del("Access-Control-Allow-Credentials")
}
if !DisableHeaderHardening {
resp.Header.Del("Strict-Transport-Security")
resp.Header.Del("X-Content-Type-Options")
resp.Header.Del("Content-Security-Policy")
@@ -238,7 +235,7 @@ func RouteTo(route utils.ProxyRouteConfig) http.Handler {
}
if(routeType == "SERVAPP" || routeType == "PROXY") {
proxy, err := NewProxy(destination, route.AcceptInsecureHTTPSTarget, route.DisableHeaderHardening, route.CORSOrigin, route)
proxy, err := NewProxy(destination, route.AcceptInsecureHTTPSTarget, route.DisableHeaderHardening, route)
if err != nil {
utils.Error("Create Route", err)
}
+1 -1
View File
@@ -151,7 +151,7 @@ func RouterGen(route utils.ProxyRouteConfig, router *mux.Router, destination htt
originCORS := route.CORSOrigin
if originCORS == "" {
if originCORS == "" && !route.DisableHeaderHardening {
if route.UseHost {
originCORS = route.Host
} else {
+2 -2
View File
@@ -224,7 +224,7 @@ func InitSnapRAIDConfig() {
Name: "SnapRAID sync " + raidOptions.Name,
Crontab: raidOptions.SyncCrontab,
Cancellable: true,
Job: cron.JobFromCommand("snapraid", "sync", "-c", utils.CONFIGFOLDER + "snapraid/" + raidOptions.Name + ".conf"),
Job: cron.JobFromCommand("snapraid", "-q", "sync", "-c", utils.CONFIGFOLDER + "snapraid/" + raidOptions.Name + ".conf"),
})
cron.RegisterJob(cron.ConfigJob{
@@ -232,7 +232,7 @@ func InitSnapRAIDConfig() {
Name: "SnapRAID scrub " + raidOptions.Name,
Crontab: raidOptions.ScrubCrontab,
Cancellable: true,
Job: cron.JobFromCommand("snapraid", "scrub", "-c", utils.CONFIGFOLDER + "snapraid/" + raidOptions.Name + ".conf"),
Job: cron.JobFromCommand("snapraid", "-q", "scrub", "-c", utils.CONFIGFOLDER + "snapraid/" + raidOptions.Name + ".conf"),
})
}
}