[release] v0.9.15
This commit is contained in:
parent
3d8d411dd4
commit
0801799600
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
},[]);
|
},[]);
|
||||||
|
|
|
@ -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') {
|
||||||
|
|
|
@ -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 });
|
||||||
|
|
|
@ -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 });
|
||||||
|
|
|
@ -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');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -34,4 +34,15 @@ export const debounce = (func, wait) => {
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
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;
|
||||||
|
}
|
|
@ -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": {
|
||||||
|
|
|
@ -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
|
||||||
|
@ -32,9 +44,14 @@ func UploadBackground(w http.ResponseWriter, req *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
// 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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue