[release] v0.9.15

This commit is contained in:
Yann Stepienik 2023-07-28 10:28:15 +01:00
parent 3d8d411dd4
commit 0801799600
13 changed files with 74 additions and 41 deletions

View file

@ -1,3 +1,9 @@
## Version 0.9.15
- Check background extension on upload is an image
- Update Docker for security patch
- Check redirect target is local
- Improve OpenID client secret generation
## Version 0.9.14 ## Version 0.9.14
- Check network mode before pruning networks - Check network mode before pruning networks

View file

@ -12,6 +12,7 @@ import * as indexDemo from './index.demo';
import * as marketDemo from './market.demo'; import * as marketDemo from './market.demo';
import wrap from './wrap'; import wrap from './wrap';
import { redirectToLocal } from '../utils/indexs';
export let CPU_ARCH = 'amd64'; export let CPU_ARCH = 'amd64';
export let CPU_AVX = true; export let CPU_AVX = true;
@ -39,7 +40,7 @@ let getStatus = (initial) => {
return response return response
}).catch((response) => { }).catch((response) => {
const urlSearch = encodeURIComponent(window.location.search); const urlSearch = encodeURIComponent(window.location.search);
const redirectTo = (window.location.pathname + urlSearch); const redirectToURL = (window.location.pathname + urlSearch);
if(response.status != 'OK') { if(response.status != 'OK') {
if( if(
@ -50,13 +51,13 @@ let getStatus = (initial) => {
window.location.href.indexOf('/cosmos-ui/register') == -1 && window.location.href.indexOf('/cosmos-ui/register') == -1 &&
window.location.href.indexOf('/cosmos-ui/forgot-password') == -1) { window.location.href.indexOf('/cosmos-ui/forgot-password') == -1) {
if(response.status == 'NEW_INSTALL') { if(response.status == 'NEW_INSTALL') {
window.location.href = '/cosmos-ui/newInstall'; redirectToLocal('/cosmos-ui/newInstall');
} else if (response.status == 'error' && response.code == "HTTP004") { } else if (response.status == 'error' && response.code == "HTTP004") {
window.location.href = '/cosmos-ui/login?redirect=' + redirectTo; redirectToLocal('/cosmos-ui/login?redirect=' + redirectToURL);
} else if (response.status == 'error' && response.code == "HTTP006") { } else if (response.status == 'error' && response.code == "HTTP006") {
window.location.href = '/cosmos-ui/loginmfa?redirect=' + redirectTo; redirectToLocal('/cosmos-ui/loginmfa?redirect=' + redirectToURL);
} else if (response.status == 'error' && response.code == "HTTP007") { } else if (response.status == 'error' && response.code == "HTTP007") {
window.location.href = '/cosmos-ui/newmfa?redirect=' + redirectTo; redirectToLocal('/cosmos-ui/newmfa?redirect=' + redirectToURL);
} }
} else { } else {
return "nothing"; return "nothing";

View file

@ -1,22 +1,23 @@
import * as API from './api'; import * as API from './api';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { redirectToLocal } from './utils/indexs';
const IsLoggedIn = () => useEffect(() => { const IsLoggedIn = () => useEffect(() => {
console.log("CHECK LOGIN") console.log("CHECK LOGIN")
const urlSearch = encodeURIComponent(window.location.search); const urlSearch = encodeURIComponent(window.location.search);
const redirectTo = (window.location.pathname + urlSearch); const redirectToURL = (window.location.pathname + urlSearch);
API.auth.me().then((data) => { API.auth.me().then((data) => {
if(data.status != 'OK') { if(data.status != 'OK') {
if(data.status == 'NEW_INSTALL') { if(data.status == 'NEW_INSTALL') {
window.location.href = '/cosmos-ui/newInstall'; redirectToLocal('/cosmos-ui/newInstall');
} else if (data.status == 'error' && data.code == "HTTP004") { } else if (data.status == 'error' && data.code == "HTTP004") {
window.location.href = '/cosmos-ui/login?redirect=' + redirectTo; redirectToLocal('/cosmos-ui/login?redirect=' + redirectToURL);
} else if (data.status == 'error' && data.code == "HTTP006") { } else if (data.status == 'error' && data.code == "HTTP006") {
window.location.href = '/cosmos-ui/loginmfa?redirect=' + redirectTo; redirectToLocal('/cosmos-ui/loginmfa?redirect=' + redirectToURL);
} else if (data.status == 'error' && data.code == "HTTP007") { } else if (data.status == 'error' && data.code == "HTTP007") {
window.location.href = '/cosmos-ui/newmfa?redirect=' + redirectTo; redirectToLocal('/cosmos-ui/newmfa?redirect=' + redirectToURL);
} }
} }
}) })

View file

@ -9,6 +9,7 @@ import AuthWrapper from './AuthWrapper';
import { useEffect } from 'react'; import { useEffect } from 'react';
import * as API from '../../api'; import * as API from '../../api';
import { redirectTo } from '../../utils/indexs';
// ================================|| REGISTER ||================================ // // ================================|| REGISTER ||================================ //
@ -17,7 +18,7 @@ const Logout = () => {
API.auth.logout() API.auth.logout()
.then(() => { .then(() => {
setTimeout(() => { setTimeout(() => {
window.location.href = '/cosmos-ui/login'; redirectToLocal('/cosmos-ui/login');
}, 2000); }, 2000);
}); });
},[]); },[]);

View file

@ -31,6 +31,7 @@ import AnimateButton from '../../../components/@extended/AnimateButton';
// assets // assets
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'; import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
import { LoadingButton } from '@mui/lab'; import { LoadingButton } from '@mui/lab';
import { redirectToLocal } from '../../../utils/indexs';
// ============================|| FIREBASE - LOGIN ||============================ // // ============================|| FIREBASE - LOGIN ||============================ //
@ -53,14 +54,14 @@ const AuthLogin = () => {
const notLogged = urlSearchParams.get('notlogged') == 1; const notLogged = urlSearchParams.get('notlogged') == 1;
const notLoggedAdmin = urlSearchParams.get('notlogged') == 2; const notLoggedAdmin = urlSearchParams.get('notlogged') == 2;
const invalid = urlSearchParams.get('invalid') == 1; const invalid = urlSearchParams.get('invalid') == 1;
const redirectTo = urlSearchParams.get('redirect') ? urlSearchParams.get('redirect') : '/cosmos-ui'; const redirectToURL = urlSearchParams.get('redirect') ? urlSearchParams.get('redirect') : '/cosmos-ui';
useEffect(() => { useEffect(() => {
API.auth.me().then((data) => { API.auth.me().then((data) => {
if(data.status == 'OK') { if(data.status == 'OK') {
window.location.href = redirectTo; redirectToLocal(redirectToURL);
} else if(data.status == 'NEW_INSTALL') { } else if(data.status == 'NEW_INSTALL') {
window.location.href = '/cosmos-ui/newInstall'; redirectToLocal('/cosmos-ui/newInstall');
} }
}); });
@ -103,7 +104,7 @@ const AuthLogin = () => {
return API.auth.login(values).then((data) => { return API.auth.login(values).then((data) => {
setStatus({ success: true }); setStatus({ success: true });
setSubmitting(false); setSubmitting(false);
window.location.href = redirectTo; redirectToLocal(redirectToURL);
}).catch((err) => { }).catch((err) => {
setStatus({ success: false }); setStatus({ success: false });
if(err.code == 'UL001') { if(err.code == 'UL001') {

View file

@ -33,6 +33,7 @@ import { strengthColor, strengthIndicator } from '../../../utils/password-streng
// assets // assets
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'; import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
import { LoadingButton } from '@mui/lab'; import { LoadingButton } from '@mui/lab';
import { redirectTo } from '../../../utils/indexs';
// ============================|| FIREBASE - REGISTER ||============================ // // ============================|| FIREBASE - REGISTER ||============================ //
@ -85,7 +86,7 @@ const AuthRegister = ({nickname, isRegister, isInviteLink, regkey}) => {
}).then((res) => { }).then((res) => {
setStatus({ success: true }); setStatus({ success: true });
setSubmitting(false); setSubmitting(false);
window.location.href = '/cosmos-ui/login'; redirectToLocal('/cosmos-ui/login');
}).catch((err) => { }).catch((err) => {
setStatus({ success: false }); setStatus({ success: false });
setErrors({ submit: err.message }); setErrors({ submit: err.message });

View file

@ -32,17 +32,18 @@ import { useTheme } from '@mui/material/styles';
import { Formik } from 'formik'; import { Formik } from 'formik';
import { LoadingButton } from '@mui/lab'; import { LoadingButton } from '@mui/lab';
import { CosmosCollapse } from '../config/users/formShortcuts'; import { CosmosCollapse } from '../config/users/formShortcuts';
import { redirectToLocal } from '../../utils/indexs';
const MFALoginForm = () => { const MFALoginForm = () => {
const urlSearchParams = new URLSearchParams(window.location.search); const urlSearchParams = new URLSearchParams(window.location.search);
const redirectTo = urlSearchParams.get('redirect') ? urlSearchParams.get('redirect') : '/cosmos-ui'; const redirectToURL = urlSearchParams.get('redirect') ? urlSearchParams.get('redirect') : '/cosmos-ui';
useEffect(() => { useEffect(() => {
API.auth.me().then((data) => { API.auth.me().then((data) => {
if(data.status == 'OK') { if(data.status == 'OK') {
window.location.href = redirectTo; redirectToLocal(redirectToURL);
} else if(data.status == 'NEW_INSTALL') { } else if(data.status == 'NEW_INSTALL') {
window.location.href = '/cosmos-ui/newInstall'; redirectToLocal('/cosmos-ui/newInstall');
} }
}); });
}); });
@ -56,7 +57,7 @@ const MFALoginForm = () => {
})} })}
onSubmit={(values, { setSubmitting, setStatus, setErrors }) => { onSubmit={(values, { setSubmitting, setStatus, setErrors }) => {
API.users.check2FA(values.token).then((data) => { API.users.check2FA(values.token).then((data) => {
window.location.href = redirectTo; redirectToLocal(redirectToURL);
}).catch((error) => { }).catch((error) => {
console.log(error) console.log(error)
setStatus({ success: false }); setStatus({ success: false });

View file

@ -8,6 +8,7 @@ import { getFaviconURL } from '../../../utils/routes';
import * as API from '../../../api'; import * as API from '../../../api';
import { CheckOutlined, ClockCircleOutlined, DashboardOutlined, DeleteOutlined, DownOutlined, LockOutlined, UpOutlined } from "@ant-design/icons"; import { CheckOutlined, ClockCircleOutlined, DashboardOutlined, DeleteOutlined, DownOutlined, LockOutlined, UpOutlined } from "@ant-design/icons";
import IsLoggedIn from '../../../isLoggedIn'; import IsLoggedIn from '../../../isLoggedIn';
import { redirectTo } from '../../../utils/indexs';
const info = { const info = {
backgroundColor: 'rgba(0, 0, 0, 0.1)', backgroundColor: 'rgba(0, 0, 0, 0.1)',
@ -22,7 +23,7 @@ const RouteOverview = ({ routeConfig }) => {
function deleteRoute(event) { function deleteRoute(event) {
event.stopPropagation(); event.stopPropagation();
API.config.deleteRoute(routeConfig.Name).then(() => { API.config.deleteRoute(routeConfig.Name).then(() => {
window.location.href = '/cosmos-ui/config-url'; redirectToLocal('/cosmos-ui/config-url');
}); });
} }

View file

@ -19,7 +19,7 @@ import { CosmosCheckbox, CosmosInputPassword, CosmosInputText, CosmosSelect } fr
import AnimateButton from '../../components/@extended/AnimateButton'; import AnimateButton from '../../components/@extended/AnimateButton';
import { Box } from '@mui/system'; import { Box } from '@mui/system';
import { pull } from 'lodash'; import { pull } from 'lodash';
import { isDomain } from '../../utils/indexs'; import { isDomain, redirectTo } from '../../utils/indexs';
import { DnsChallengeComp } from '../../utils/dns-challenge-comp'; import { DnsChallengeComp } from '../../utils/dns-challenge-comp';
// ================================|| LOGIN ||================================ // // ================================|| LOGIN ||================================ //
@ -67,7 +67,7 @@ const NewInstall = () => {
setStatus(res.data); setStatus(res.data);
} catch(error) { } catch(error) {
if(error.status == 401) if(error.status == 401)
window.location.href = "/cosmos-ui/login"; redirectToLocal("/cosmos-ui/login");
} }
if (typeof status !== 'undefined') { if (typeof status !== 'undefined') {
setTimeout(() => { setTimeout(() => {
@ -618,7 +618,7 @@ const NewInstall = () => {
step: "5", step: "5",
}) })
setTimeout(() => { setTimeout(() => {
window.location.href = hostname + "/cosmos-ui/login"; redirectTo(hostname + "/cosmos-ui/login");
}, 500); }, 500);
} else { } else {
setActiveStep(activeStep + 1) setActiveStep(activeStep + 1)

View file

@ -114,7 +114,11 @@ const OpenIdList = () => {
}, []); }, []);
const generateNewSecret = (clientIdToUpdate) => { const generateNewSecret = (clientIdToUpdate) => {
let newSecret = Math.random().toString(36).substring(2, 24) + Math.random().toString(36).substring(2, 15); let newSecretSeed = window.crypto.getRandomValues(new Uint32Array(4));
let newSecret = "";
newSecretSeed.forEach((r) => {
newSecret += r.toString(36);
});
let encryptedSecret = bcrypt.hashSync(newSecret, 10); let encryptedSecret = bcrypt.hashSync(newSecret, 10);
let index = clients.findIndex((r) => r.id === clientIdToUpdate); let index = clients.findIndex((r) => r.id === clientIdToUpdate);
clients[index].secret = encryptedSecret; clients[index].secret = encryptedSecret;

View file

@ -35,3 +35,14 @@ export const debounce = (func, wait) => {
timeout = setTimeout(() => func.apply(context, args), wait); timeout = setTimeout(() => func.apply(context, args), wait);
}; };
}; };
export const redirectTo = (url) => {
window.location.href = url;
}
export const redirectToLocal = (url) => {
if(url.startsWith("http://") || url.startsWith("https://")) {
throw new Error("URL must be local");
}
window.location.href = url;
}

View file

@ -1,6 +1,6 @@
{ {
"name": "cosmos-server", "name": "cosmos-server",
"version": "0.9.14", "version": "0.9.15",
"description": "", "description": "",
"main": "test-server.js", "main": "test-server.js",
"bugs": { "bugs": {

View file

@ -12,6 +12,18 @@ import (
"github.com/azukaar/cosmos-server/src/utils" "github.com/azukaar/cosmos-server/src/utils"
) )
var validExtensions = map[string]bool{
".jpg": true,
".jpeg": true,
".png": true,
".gif": true,
".bmp": true,
".svg": true,
".webp": true,
".tiff": true,
".avif": true,
}
func UploadBackground(w http.ResponseWriter, req *http.Request) { func UploadBackground(w http.ResponseWriter, req *http.Request) {
if utils.AdminOnly(w, req) != nil { if utils.AdminOnly(w, req) != nil {
return return
@ -36,6 +48,11 @@ func UploadBackground(w http.ResponseWriter, req *http.Request) {
// get the file extension // get the file extension
ext := filepath.Ext(header.Filename) ext := filepath.Ext(header.Filename)
if !validExtensions[ext] {
utils.HTTPError(w, "Invalid file extension " + ext, http.StatusBadRequest, "FILE001")
return
}
// create a new file in the config directory // create a new file in the config directory
dst, err := os.Create("/config/background" + ext) dst, err := os.Create("/config/background" + ext)
if err != nil { if err != nil {
@ -75,19 +92,7 @@ func GetBackground(w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req) vars := mux.Vars(req)
ext := vars["ext"] ext := vars["ext"]
validExtensions := map[string]bool{ if !validExtensions["." + ext] {
"jpg": true,
"jpeg": true,
"png": true,
"gif": true,
"bmp": true,
"svg": true,
"webp": true,
"tiff": true,
"avif": true,
}
if !validExtensions[ext] {
utils.HTTPError(w, "Invalid file extension", http.StatusBadRequest, "FILE001") utils.HTTPError(w, "Invalid file extension", http.StatusBadRequest, "FILE001")
return return
} }