[release] v0.13.0-unstable8
This commit is contained in:
parent
49d7dd7d4a
commit
9085b2587c
17 changed files with 326 additions and 162 deletions
|
@ -1,6 +1,8 @@
|
|||
## Version 0.13.0
|
||||
- Display containers as stacks
|
||||
- New Delete modal to delete services entirely
|
||||
- Upload custom icons to containers
|
||||
- improve backup file, by splitting cosmos out to a separate docker-compose.yml file
|
||||
- Cosmos-networks now have specific names instead for a generic names
|
||||
- Fix issue where search bar reset when deleting volume/network
|
||||
- Fix breadcrumbs in subpaths
|
||||
|
@ -9,7 +11,8 @@
|
|||
- Edit container user and devices from UI
|
||||
- Fix bug where Cosmos Constellation's UDP ports by a TCP one
|
||||
- Support array command and single device in docker-compose import
|
||||
- Add default alert.. by default
|
||||
- Add default alerts... by default (was missing from the default config)
|
||||
- disable few features liks Constellation, Backup and Monitoring when in install mode to reduce logs and prevent issues with the DB
|
||||
|
||||
## Version 0.12.6
|
||||
- Fix a security issue with cross-domain APIs availability
|
||||
|
|
|
@ -78,7 +78,7 @@ export const checkHost = (host) => {
|
|||
});
|
||||
}
|
||||
|
||||
export const uploadBackground = (file) => {
|
||||
export const uploadImage = (file) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
|
|
|
@ -199,10 +199,10 @@ let getDNS = (host) => {
|
|||
});
|
||||
}
|
||||
|
||||
let uploadBackground = (file) => {
|
||||
let uploadImage = (file, name) => {
|
||||
const formData = new FormData();
|
||||
formData.append('background', file);
|
||||
return wrap(fetch('/cosmos/api/background', {
|
||||
formData.append('image', file);
|
||||
return wrap(fetch('/cosmos/api/upload/' + name, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
}));
|
||||
|
@ -229,7 +229,7 @@ if(isDemo) {
|
|||
isOnline = indexDemo.isOnline;
|
||||
checkHost = indexDemo.checkHost;
|
||||
getDNS = indexDemo.getDNS;
|
||||
uploadBackground = indexDemo.uploadBackground;
|
||||
uploadImage = indexDemo.uploadImage;
|
||||
constellation = constellationDemo;
|
||||
metrics = metricsDemo;
|
||||
}
|
||||
|
@ -247,5 +247,5 @@ export {
|
|||
checkHost,
|
||||
getDNS,
|
||||
metrics,
|
||||
uploadBackground
|
||||
uploadImage
|
||||
};
|
|
@ -13,6 +13,7 @@ import { CosmosCheckbox } from '../users/formShortcuts';
|
|||
import { Field } from 'formik';
|
||||
import MiniPlotComponent from '../../dashboard/components/mini-plot';
|
||||
import ImageWithPlaceholder from '../../../components/imageWithPlaceholder';
|
||||
import UploadButtons from '../../../components/fileUpload';
|
||||
|
||||
const info = {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.1)',
|
||||
|
|
|
@ -316,10 +316,10 @@ const ConfigManagement = () => {
|
|||
<MainCard title="Appearance">
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12}>
|
||||
{!uploadingBackground && formik.values.Background && <img src=
|
||||
{formik.values.Background} alt="preview seems broken. Please re-upload."
|
||||
width={285} />}
|
||||
{uploadingBackground && <Skeleton variant="rectangular" width={285} height={140} />}
|
||||
{!uploadingBackground && formik.values.Background && <img src=
|
||||
{formik.values.Background} alt="preview seems broken. Please re-upload."
|
||||
width={285} />}
|
||||
{uploadingBackground && <Skeleton variant="rectangular" width={285} height={140} />}
|
||||
<Stack spacing={1} direction="row">
|
||||
<UploadButtons
|
||||
accept='.jpg, .png, .gif, .jpeg, .webp, .bmp, .avif, .tiff, .svg'
|
||||
|
@ -327,8 +327,8 @@ const ConfigManagement = () => {
|
|||
OnChange={(e) => {
|
||||
setUploadingBackground(true);
|
||||
const file = e.target.files[0];
|
||||
API.uploadBackground(file).then((data) => {
|
||||
formik.setFieldValue('Background', "/cosmos/api/background/" + data.data.extension.replace(".", ""));
|
||||
API.uploadImage(file, "background").then((data) => {
|
||||
formik.setFieldValue('Background', data.data.path);
|
||||
setUploadingBackground(false);
|
||||
});
|
||||
}}
|
||||
|
|
|
@ -69,9 +69,9 @@ const NewDockerServiceForm = () => {
|
|||
image: containerInfo.Config.Image,
|
||||
environment: containerInfo.Config.Env,
|
||||
labels: containerInfo.Config.Labels,
|
||||
devices: containerInfo.HostConfig.Devices.map((device) => {
|
||||
devices: containerInfo.HostConfig.Devices ? containerInfo.HostConfig.Devices.map((device) => {
|
||||
return `${device.PathOnHost}:${device.PathInContainer}:`;
|
||||
}),
|
||||
}) : [],
|
||||
expose: containerInfo.Config.ExposedPorts,
|
||||
tty: containerInfo.Config.Tty,
|
||||
stdin_open: containerInfo.Config.OpenStdin,
|
||||
|
|
|
@ -10,6 +10,7 @@ import RestartModal from '../../config/users/restart';
|
|||
import GetActions from '../actionBar';
|
||||
import { ServAppIcon } from '../../../utils/servapp-icon';
|
||||
import MiniPlotComponent from '../../dashboard/components/mini-plot';
|
||||
import UploadButtons from '../../../components/fileUpload';
|
||||
|
||||
const info = {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.1)',
|
||||
|
@ -87,6 +88,25 @@ const ContainerOverview = ({ containerInfo, config, refresh, updatesAvailable, s
|
|||
"dead": <Chip label="Dead" color="error" />,
|
||||
})[State.Status]}
|
||||
</div>
|
||||
<UploadButtons
|
||||
accept='.jpg, .png, .gif, .jpeg, .webp, .bmp, .avif, .tiff, .svg'
|
||||
label="icon"
|
||||
OnChange={(e) => {
|
||||
const file = e.target.files[0];
|
||||
setIsUpdating(true);
|
||||
API.uploadImage(file, "servapp-" + Name.replace('/', '')).then((data) => {
|
||||
API.docker.updateContainer(Name.replace('/', ''), {
|
||||
labels: {
|
||||
...Config.Labels,
|
||||
"cosmos-icon": data.data.path,
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
refreshAll();
|
||||
});
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
<Stack spacing={2} style={{ width: '100%' }} >
|
||||
|
|
|
@ -71,11 +71,11 @@ const DockerContainerSetup = ({ noCard, containerInfo, installer, OnChange, refr
|
|||
labels: Object.keys(containerInfo.Config.Labels).map((key) => {
|
||||
return { key, value: containerInfo.Config.Labels[key] };
|
||||
}),
|
||||
devices: containerInfo.HostConfig.Devices.map((device) => {
|
||||
devices: containerInfo.HostConfig.Devices ? containerInfo.HostConfig.Devices.map((device) => {
|
||||
return (typeof device == "string") ?
|
||||
{ key: device.split(":")[0], value: (device.split(":")[1] || device.split(":")[0]) }
|
||||
: { key: device.PathOnHost, value: device.PathInContainer };
|
||||
}),
|
||||
}) : [],
|
||||
interactive: containerInfo.Config.Tty && containerInfo.Config.OpenStdin,
|
||||
}}
|
||||
enableReinitialize
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "cosmos-server",
|
||||
"version": "0.13.0-unstable7",
|
||||
"version": "0.13.0-unstable8",
|
||||
"description": "",
|
||||
"main": "test-server.js",
|
||||
"bugs": {
|
||||
|
|
|
@ -126,6 +126,7 @@ func CRON() {
|
|||
s.Every(1).Day().At("00:00").Do(func() {
|
||||
utils.CleanupByDate("notifications")
|
||||
utils.CleanupByDate("events")
|
||||
imageCleanUp()
|
||||
})
|
||||
s.Start()
|
||||
}()
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"io"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"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) {
|
||||
if utils.AdminOnly(w, req) != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if(req.Method == "POST") {
|
||||
// parse the form data
|
||||
err := req.ParseMultipartForm(1 << 20)
|
||||
if err != nil {
|
||||
utils.HTTPError(w, "Error parsing form data", http.StatusInternalServerError, "FORM001")
|
||||
return
|
||||
}
|
||||
|
||||
// retrieve the file part of the form
|
||||
file, header, err := req.FormFile("background")
|
||||
if err != nil {
|
||||
utils.HTTPError(w, "Error retrieving file from form data", http.StatusInternalServerError, "FORM002")
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// get the file extension
|
||||
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
|
||||
dst, err := os.Create(utils.CONFIGFOLDER + "background" + ext)
|
||||
if err != nil {
|
||||
utils.HTTPError(w, "Error creating destination file", http.StatusInternalServerError, "FILE004")
|
||||
return
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
// copy the uploaded file to the destination file
|
||||
if _, err := io.Copy(dst, file); err != nil {
|
||||
utils.HTTPError(w, "Error writing to destination file", http.StatusInternalServerError, "FILE005")
|
||||
return
|
||||
}
|
||||
|
||||
// return a response to the client
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"status": "OK",
|
||||
"data": map[string]interface{}{
|
||||
"filename": header.Filename,
|
||||
"size": header.Size,
|
||||
"extension": ext,
|
||||
},
|
||||
})
|
||||
|
||||
} else {
|
||||
utils.Error("UploadBackground: Method not allowed - " + req.Method, nil)
|
||||
utils.HTTPError(w, "Method not allowed", http.StatusMethodNotAllowed, "HTTP001")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func GetBackground(w http.ResponseWriter, req *http.Request) {
|
||||
if utils.LoggedInOnly(w, req) != nil {
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(req)
|
||||
ext := vars["ext"]
|
||||
|
||||
if !validExtensions["." + ext] {
|
||||
utils.HTTPError(w, "Invalid file extension", http.StatusBadRequest, "FILE001")
|
||||
return
|
||||
}
|
||||
|
||||
if(req.Method == "GET") {
|
||||
// get the background image
|
||||
bg, err := ioutil.ReadFile(utils.CONFIGFOLDER + "background." + ext)
|
||||
if err != nil {
|
||||
utils.HTTPError(w, "Error reading background image", http.StatusInternalServerError, "FILE003")
|
||||
return
|
||||
}
|
||||
|
||||
// return a response to the client
|
||||
w.Header().Set("Content-Type", "image/" + ext)
|
||||
w.Write(bg)
|
||||
|
||||
} else {
|
||||
utils.Error("GetBackground: Method not allowed - " + req.Method, nil)
|
||||
utils.HTTPError(w, "Method not allowed", http.StatusMethodNotAllowed, "HTTP001")
|
||||
return
|
||||
}
|
||||
}
|
|
@ -1013,8 +1013,6 @@ func CreateService(serviceRequest DockerServiceCreateRequest, OnLog func(string)
|
|||
func ReOrderServices(serviceMap map[string]ContainerCreateRequestContainer) ([]ContainerCreateRequestContainer, error) {
|
||||
startOrder := []ContainerCreateRequestContainer{}
|
||||
|
||||
utils.Debug(fmt.Sprintf("ReOrderServices: start: %s", serviceMap))
|
||||
|
||||
for len(serviceMap) > 0 {
|
||||
// Keep track of whether we've added any services in this iteration
|
||||
changed := false
|
||||
|
|
|
@ -7,6 +7,8 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"bytes"
|
||||
"gopkg.in/yaml.v2"
|
||||
"os"
|
||||
|
||||
"github.com/azukaar/cosmos-server/src/utils"
|
||||
"github.com/docker/docker/api/types"
|
||||
|
@ -18,12 +20,17 @@ import (
|
|||
var ExportError = ""
|
||||
|
||||
func ExportDocker() {
|
||||
config := utils.GetMainConfig()
|
||||
if config.NewInstall {
|
||||
return
|
||||
}
|
||||
|
||||
ExportError = ""
|
||||
|
||||
errD := Connect()
|
||||
if errD != nil {
|
||||
ExportError = "Export Docker - cannot connect - " + errD.Error()
|
||||
utils.Error("ExportDocker - connect - ", errD)
|
||||
utils.MajorError("ExportDocker - connect - ", errD)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -32,7 +39,7 @@ func ExportDocker() {
|
|||
// List containers
|
||||
containers, err := DockerClient.ContainerList(DockerContext, types.ContainerListOptions{})
|
||||
if err != nil {
|
||||
utils.Error("ExportDocker - Cannot list containers", err)
|
||||
utils.MajorError("ExportDocker - Cannot list containers", err)
|
||||
ExportError = "Export Docker - Cannot list containers - " + err.Error()
|
||||
return
|
||||
}
|
||||
|
@ -44,7 +51,7 @@ func ExportDocker() {
|
|||
// Fetch detailed info of each container
|
||||
detailedInfo, err := DockerClient.ContainerInspect(DockerContext, container.ID)
|
||||
if err != nil {
|
||||
utils.Error("Export Docker - Cannot inspect container" + container.Names[0], err)
|
||||
utils.MajorError("Export Docker - Cannot inspect container" + container.Names[0], err)
|
||||
ExportError = "Export Docker - Cannot inspect container" + container.Names[0] + " - " + err.Error()
|
||||
return
|
||||
}
|
||||
|
@ -118,11 +125,11 @@ func ExportDocker() {
|
|||
// Networks
|
||||
Networks: func() map[string]ContainerCreateRequestServiceNetwork {
|
||||
networks := make(map[string]ContainerCreateRequestServiceNetwork)
|
||||
for netName, netConfig := range detailedInfo.NetworkSettings.Networks {
|
||||
for netName, _ := range detailedInfo.NetworkSettings.Networks {
|
||||
networks[netName] = ContainerCreateRequestServiceNetwork{
|
||||
Aliases: netConfig.Aliases,
|
||||
IPV4Address: netConfig.IPAddress,
|
||||
IPV6Address: netConfig.GlobalIPv6Address,
|
||||
// Aliases: netConfig.Aliases,
|
||||
// IPV4Address: netConfig.IPAddress,
|
||||
// IPV6Address: netConfig.GlobalIPv6Address,
|
||||
}
|
||||
}
|
||||
return networks
|
||||
|
@ -175,7 +182,7 @@ func ExportDocker() {
|
|||
// List networks
|
||||
networks, err := DockerClient.NetworkList(DockerContext, types.NetworkListOptions{})
|
||||
if err != nil {
|
||||
utils.Error("Export Docker - Cannot list networks", err)
|
||||
utils.MajorError("Export Docker - Cannot list networks", err)
|
||||
ExportError = "Export Docker - Cannot list networks - " + err.Error()
|
||||
return
|
||||
}
|
||||
|
@ -191,7 +198,7 @@ func ExportDocker() {
|
|||
// Fetch detailed info of each network
|
||||
detailedInfo, err := DockerClient.NetworkInspect(DockerContext, network.ID, types.NetworkInspectOptions{})
|
||||
if err != nil {
|
||||
utils.Error("Export Docker - Cannot inspect network", err)
|
||||
utils.MajorError("Export Docker - Cannot inspect network", err)
|
||||
ExportError = "Export Docker - Cannot inspect network - " + err.Error()
|
||||
return
|
||||
}
|
||||
|
@ -217,6 +224,47 @@ func ExportDocker() {
|
|||
finalBackup.Networks[detailedInfo.Name] = network
|
||||
}
|
||||
|
||||
// remove cosmos from services
|
||||
if os.Getenv("HOSTNAME") != "" {
|
||||
cosmos := services[os.Getenv("HOSTNAME")]
|
||||
delete(services, os.Getenv("HOSTNAME"))
|
||||
|
||||
// export separately cosmos
|
||||
// Create a buffer to hold the JSON output
|
||||
var buf bytes.Buffer
|
||||
|
||||
// Create a new yaml encoder that writes to the buffer
|
||||
encoder := yaml.NewEncoder(&buf)
|
||||
|
||||
// Set escape HTML to false to avoid escaping special characters
|
||||
// encoder.SetEscapeHTML(false)
|
||||
//format
|
||||
// encoder.SetIndent("", " ")
|
||||
|
||||
// Use the encoder to write the structured data to the buffer
|
||||
toExport := map[string]map[string]ContainerCreateRequestContainer {
|
||||
"services": map[string]ContainerCreateRequestContainer {
|
||||
os.Getenv("HOSTNAME"): cosmos,
|
||||
},
|
||||
}
|
||||
|
||||
err = encoder.Encode(toExport)
|
||||
if err != nil {
|
||||
utils.MajorError("Export Docker - Cannot marshal docker backup", err)
|
||||
ExportError = "Export Docker - Cannot marshal docker backup - " + err.Error()
|
||||
}
|
||||
|
||||
// The JSON data is now in buf.Bytes()
|
||||
yamlData := buf.Bytes()
|
||||
|
||||
// Write the JSON data to a file
|
||||
err = ioutil.WriteFile(utils.CONFIGFOLDER + "cosmos.docker-compose.yaml", yamlData, 0644)
|
||||
if err != nil {
|
||||
utils.MajorError("Export Docker - Cannot save docker backup", err)
|
||||
ExportError = "Export Docker - Cannot save docker backup - " + err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the services map to your finalBackup struct
|
||||
finalBackup.Services = services
|
||||
|
||||
|
@ -234,7 +282,7 @@ func ExportDocker() {
|
|||
// Use the encoder to write the structured data to the buffer
|
||||
err = encoder.Encode(finalBackup)
|
||||
if err != nil {
|
||||
utils.Error("Export Docker - Cannot marshal docker backup", err)
|
||||
utils.MajorError("Export Docker - Cannot marshal docker backup", err)
|
||||
ExportError = "Export Docker - Cannot marshal docker backup - " + err.Error()
|
||||
}
|
||||
|
||||
|
@ -244,7 +292,7 @@ func ExportDocker() {
|
|||
// Write the JSON data to a file
|
||||
err = ioutil.WriteFile(utils.CONFIGFOLDER + "backup.cosmos-compose.json", jsonData, 0644)
|
||||
if err != nil {
|
||||
utils.Error("Export Docker - Cannot save docker backup", err)
|
||||
utils.MajorError("Export Docker - Cannot save docker backup", err)
|
||||
ExportError = "Export Docker - Cannot save docker backup - " + err.Error()
|
||||
}
|
||||
}
|
|
@ -392,8 +392,8 @@ func InitServer() *mux.Router {
|
|||
|
||||
srapi.HandleFunc("/api/markets", market.MarketGet)
|
||||
|
||||
srapi.HandleFunc("/api/background", UploadBackground)
|
||||
srapi.HandleFunc("/api/background/{ext}", GetBackground)
|
||||
srapi.HandleFunc("/api/upload/{name}", UploadImage)
|
||||
srapi.HandleFunc("/api/image/{name}", GetImage)
|
||||
|
||||
srapi.HandleFunc("/api/get-backup", configapi.BackupFileApiGet)
|
||||
|
||||
|
|
204
src/image.go
Normal file
204
src/image.go
Normal file
|
@ -0,0 +1,204 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"io"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"fmt"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/azukaar/cosmos-server/src/utils"
|
||||
"github.com/azukaar/cosmos-server/src/docker"
|
||||
)
|
||||
|
||||
var validExtensions = map[string]bool{
|
||||
".jpg": true,
|
||||
".jpeg": true,
|
||||
".png": true,
|
||||
".gif": true,
|
||||
".bmp": true,
|
||||
".svg": true,
|
||||
".webp": true,
|
||||
".tiff": true,
|
||||
".avif": true,
|
||||
}
|
||||
|
||||
func UploadImage(w http.ResponseWriter, req *http.Request) {
|
||||
if utils.AdminOnly(w, req) != nil {
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(req)
|
||||
originalName := vars["name"]
|
||||
|
||||
name := originalName + "-" + utils.GenerateRandomString(6)
|
||||
|
||||
// if name includes / or ..
|
||||
if filepath.Clean(name) != name || strings.Contains(name, "/") {
|
||||
utils.HTTPError(w, "Invalid file name", http.StatusBadRequest, "FILE002")
|
||||
return
|
||||
}
|
||||
|
||||
if(req.Method == "POST") {
|
||||
// if the uploads directory does not exist, create it
|
||||
if _, err := os.Stat(utils.CONFIGFOLDER + "/uploads"); os.IsNotExist(err) {
|
||||
os.Mkdir(utils.CONFIGFOLDER + "/uploads", 0750)
|
||||
}
|
||||
|
||||
// parse the form data
|
||||
err := req.ParseMultipartForm(1 << 20)
|
||||
if err != nil {
|
||||
utils.HTTPError(w, "Error parsing form data", http.StatusInternalServerError, "FORM001")
|
||||
return
|
||||
}
|
||||
|
||||
// retrieve the file part of the form
|
||||
file, header, err := req.FormFile("image")
|
||||
if err != nil {
|
||||
utils.HTTPError(w, "Error retrieving file from form data", http.StatusInternalServerError, "FORM002")
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// get the file extension
|
||||
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
|
||||
dst, err := os.Create(utils.CONFIGFOLDER + "/uploads/" + name + ext)
|
||||
if err != nil {
|
||||
utils.HTTPError(w, "Error creating destination file", http.StatusInternalServerError, "FILE004")
|
||||
return
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
// copy the uploaded file to the destination file
|
||||
if _, err := io.Copy(dst, file); err != nil {
|
||||
utils.HTTPError(w, "Error writing to destination file", http.StatusInternalServerError, "FILE005")
|
||||
return
|
||||
}
|
||||
|
||||
// return a response to the client
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"status": "OK",
|
||||
"data": map[string]interface{}{
|
||||
"path": "/cosmos/api/image/" + name + ext,
|
||||
"filename": header.Filename,
|
||||
"size": header.Size,
|
||||
"extension": ext,
|
||||
},
|
||||
})
|
||||
|
||||
} else {
|
||||
utils.Error("UploadBackground: Method not allowed - " + req.Method, nil)
|
||||
utils.HTTPError(w, "Method not allowed", http.StatusMethodNotAllowed, "HTTP001")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func GetImage(w http.ResponseWriter, req *http.Request) {
|
||||
if utils.LoggedInOnly(w, req) != nil {
|
||||
return
|
||||
}
|
||||
|
||||
utils.Log("API: GetImage")
|
||||
|
||||
vars := mux.Vars(req)
|
||||
name := vars["name"]
|
||||
|
||||
// if name includes / or ..
|
||||
if filepath.Clean(name) != name || strings.Contains(name, "/") {
|
||||
utils.Error("GetBackground: Invalid file name - " + name, nil)
|
||||
utils.HTTPError(w, "Invalid file name", http.StatusBadRequest, "FILE002")
|
||||
return
|
||||
}
|
||||
|
||||
// get the file extension
|
||||
ext := filepath.Ext(name)
|
||||
|
||||
if !validExtensions[ext] {
|
||||
utils.Error("GetBackground: Invalid file extension - " + ext, nil)
|
||||
utils.HTTPError(w, "Invalid file extension", http.StatusBadRequest, "FILE001")
|
||||
return
|
||||
}
|
||||
|
||||
if(req.Method == "GET") {
|
||||
// get the background image
|
||||
bg, err := ioutil.ReadFile(utils.CONFIGFOLDER + "/uploads/" + name)
|
||||
if err != nil {
|
||||
utils.Error("GetBackground: Error reading image - " + name, err)
|
||||
utils.HTTPError(w, "Error reading image", http.StatusInternalServerError, "FILE003")
|
||||
return
|
||||
}
|
||||
|
||||
// return a response to the client
|
||||
w.Header().Set("Content-Type", "image/" + ext)
|
||||
w.Write(bg)
|
||||
|
||||
} else {
|
||||
utils.Error("GetBackground: Method not allowed - " + req.Method, nil)
|
||||
utils.HTTPError(w, "Method not allowed", http.StatusMethodNotAllowed, "HTTP001")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func imageCleanUp() {
|
||||
utils.Log("Image cleanup")
|
||||
|
||||
config := utils.GetMainConfig()
|
||||
images := map[string]bool{}
|
||||
images[config.HomepageConfig.Background] = true
|
||||
|
||||
for _, route := range config.HTTPConfig.ProxyConfig.Routes {
|
||||
if(route.Icon != "") {
|
||||
images[route.Icon] = true
|
||||
}
|
||||
}
|
||||
|
||||
// get containers
|
||||
containers, err := docker.ListContainers()
|
||||
|
||||
if err != nil {
|
||||
utils.Error("Image cleanup: Error getting containers", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, container := range containers {
|
||||
if(container.Labels["cosmos-icon"] != "") {
|
||||
images[container.Labels["cosmos-icon"]] = true
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(images)
|
||||
|
||||
// if the uploads directory does not exist, return
|
||||
if _, err := os.Stat(utils.CONFIGFOLDER + "/uploads"); os.IsNotExist(err) {
|
||||
return
|
||||
}
|
||||
|
||||
// get the files in the uploads directory
|
||||
files, err := ioutil.ReadDir(utils.CONFIGFOLDER + "/uploads")
|
||||
if err != nil {
|
||||
utils.Error("Image cleanup: Error reading directory", err)
|
||||
return
|
||||
}
|
||||
|
||||
// loop through the files
|
||||
base := "/cosmos/api/image/"
|
||||
for _, f := range files {
|
||||
if(!images[base + f.Name()]) {
|
||||
err := os.Remove(utils.CONFIGFOLDER + "/uploads/" + f.Name())
|
||||
if err != nil {
|
||||
utils.Error("Image cleanup: Error removing file", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
29
src/index.go
29
src/index.go
|
@ -45,25 +45,30 @@ func main() {
|
|||
utils.Log("Docker API version: " + version.APIVersion)
|
||||
}
|
||||
|
||||
utils.Log("Starting monitoring services...")
|
||||
config := utils.GetMainConfig()
|
||||
if !config.NewInstall {
|
||||
|
||||
metrics.Init()
|
||||
utils.Log("Starting monitoring services...")
|
||||
|
||||
utils.Log("Starting market services...")
|
||||
metrics.Init()
|
||||
|
||||
market.Init()
|
||||
|
||||
utils.Log("Starting OpenID services...")
|
||||
utils.Log("Starting market services...")
|
||||
|
||||
authorizationserver.Init()
|
||||
market.Init()
|
||||
|
||||
utils.Log("Starting OpenID services...")
|
||||
|
||||
utils.Log("Starting constellation services...")
|
||||
authorizationserver.Init()
|
||||
|
||||
constellation.InitDNS()
|
||||
|
||||
constellation.Init()
|
||||
utils.Log("Starting constellation services...")
|
||||
|
||||
utils.Log("Starting server...")
|
||||
constellation.InitDNS()
|
||||
|
||||
constellation.Init()
|
||||
|
||||
utils.Log("Starting server...")
|
||||
|
||||
}
|
||||
|
||||
StartServer()
|
||||
}
|
||||
|
|
|
@ -188,6 +188,7 @@ type ProxyRouteConfig struct {
|
|||
RestrictToConstellation bool
|
||||
OverwriteHostHeader string
|
||||
WhitelistInboundIPs []string
|
||||
Icon string
|
||||
}
|
||||
|
||||
type EmailConfig struct {
|
||||
|
|
Loading…
Add table
Reference in a new issue