Skip to content

Commit

Permalink
feat: add edit of notice box content to admin settings
Browse files Browse the repository at this point in the history
  • Loading branch information
spacehamster87 committed Nov 27, 2024
1 parent 38ce40a commit 00a5786
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 3 deletions.
64 changes: 64 additions & 0 deletions internal/api/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ func (api *RestApi) MountConfigApiRoutes(r *mux.Router) {
r.HandleFunc("/users/", api.getUsers).Methods(http.MethodGet)
r.HandleFunc("/users/", api.deleteUser).Methods(http.MethodDelete)
r.HandleFunc("/user/{id}", api.updateUser).Methods(http.MethodPost)
r.HandleFunc("/notice/", api.editNotice).Methods(http.MethodPost)
}
}

Expand Down Expand Up @@ -1285,6 +1286,69 @@ func (api *RestApi) updateUser(rw http.ResponseWriter, r *http.Request) {
}
}

// editNotice godoc
// @summary Updates or empties the notice box content
// @tags User
// @description Modifies the content of notice.txt, shown as notice box on the homepage.
// @description If more than one formValue is set then only the highest priority field is used.
// @description Only accessible from IPs registered with apiAllowedIPs configuration option.
// @accept mpfd
// @produce plain
// @param new-content formData string false "Priority 1: New content to display"
// @success 200 {string} string "Success Response Message"
// @failure 400 {string} string "Bad Request"
// @failure 401 {string} string "Unauthorized"
// @failure 403 {string} string "Forbidden"
// @failure 422 {string} string "Unprocessable Entity: The user could not be updated"
// @failure 500 {string} string "Internal Server Error"
// @security ApiKeyAuth
// @router /notice/ [post]
func (api *RestApi) editNotice(rw http.ResponseWriter, r *http.Request) {
err := securedCheck(r)
if err != nil {
http.Error(rw, err.Error(), http.StatusForbidden)
return
}

if user := repository.GetUserFromContext(r.Context()); !user.HasRole(schema.RoleAdmin) {
http.Error(rw, "Only admins are allowed to update the notice.txt file", http.StatusForbidden)
return
}

// Get Value
newContent := r.FormValue("new-content")

// Check FIle
noticeExists := util.CheckFileExists("./var/notice.txt")
if !noticeExists {
ntxt, err := os.Create("./var/notice.txt")
if err != nil {
log.Errorf("Creating ./var/notice.txt failed: %s", err.Error())
http.Error(rw, err.Error(), http.StatusUnprocessableEntity)
return
}
ntxt.Close()
}

if newContent != "" {
if err := os.WriteFile("./var/notice.txt", []byte(newContent), 0o666); err != nil {
log.Errorf("Writing to ./var/notice.txt failed: %s", err.Error())
http.Error(rw, err.Error(), http.StatusUnprocessableEntity)
return
} else {
rw.Write([]byte("Update Notice Content Success"))
}
} else {
if err := os.WriteFile("./var/notice.txt", []byte(""), 0o666); err != nil {
log.Errorf("Writing to ./var/notice.txt failed: %s", err.Error())
http.Error(rw, err.Error(), http.StatusUnprocessableEntity)
return
} else {
rw.Write([]byte("Empty Notice Content Success"))
}
}
}

func (api *RestApi) getJWT(rw http.ResponseWriter, r *http.Request) {
err := securedCheck(r)
if err != nil {
Expand Down
13 changes: 12 additions & 1 deletion internal/routerConfig/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type Route struct {

var routes []Route = []Route{
{"/", "home.tmpl", "ClusterCockpit", false, setupHomeRoute},
{"/config", "config.tmpl", "Settings", false, func(i InfoType, r *http.Request) InfoType { return i }},
{"/config", "config.tmpl", "Settings", false, setupConfigRoute},
{"/monitoring/jobs/", "monitoring/jobs.tmpl", "Jobs - ClusterCockpit", true, func(i InfoType, r *http.Request) InfoType { return i }},
{"/monitoring/job/{id:[0-9]+}", "monitoring/job.tmpl", "Job <ID> - ClusterCockpit", false, setupJobRoute},
{"/monitoring/users/", "monitoring/list.tmpl", "Users - ClusterCockpit", true, func(i InfoType, r *http.Request) InfoType { i["listType"] = "USER"; return i }},
Expand Down Expand Up @@ -80,6 +80,17 @@ func setupHomeRoute(i InfoType, r *http.Request) InfoType {
return i
}

func setupConfigRoute(i InfoType, r *http.Request) InfoType {
if util.CheckFileExists("./var/notice.txt") {
msg, err := os.ReadFile("./var/notice.txt")
if err == nil {
i["ncontent"] = string(msg)
}
}

return i
}

func setupJobRoute(i InfoType, r *http.Request) InfoType {
i["id"] = mux.Vars(r)["id"]
if config.Keys.EmissionConstant != 0 {
Expand Down
3 changes: 2 additions & 1 deletion web/frontend/src/Config.root.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
export let isAdmin;
export let isApi;
export let username;
export let ncontent;
</script>

{#if isAdmin == true}
<Card style="margin-bottom: 1.5em;">
<CardHeader>
<CardTitle class="mb-1">Admin Options</CardTitle>
</CardHeader>
<AdminSettings />
<AdminSettings {ncontent}/>
</Card>
{/if}

Expand Down
3 changes: 2 additions & 1 deletion web/frontend/src/config.entrypoint.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ new Config({
props: {
isAdmin: isAdmin,
isApi: isApi,
username: username
username: username,
ncontent: ncontent,
},
context: new Map([
['cc-config', clusterCockpitConfig],
Expand Down
4 changes: 4 additions & 0 deletions web/frontend/src/config/AdminSettings.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
import AddUser from "./admin/AddUser.svelte";
import ShowUsers from "./admin/ShowUsers.svelte";
import Options from "./admin/Options.svelte";
import NoticeEdit from "./admin/NoticeEdit.svelte";
export let ncontent;
let users = [];
let roles = [];
Expand Down Expand Up @@ -52,4 +55,5 @@
<EditProject on:reload={getUserList} />
</Col>
<Options />
<NoticeEdit {ncontent}/>
</Row>
78 changes: 78 additions & 0 deletions web/frontend/src/config/admin/NoticeEdit.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<!--
@component Admin edit notice.txt content card
-->

<script>
import { Col, Card, CardTitle, CardBody } from "@sveltestrap/sveltestrap";
import { fade } from "svelte/transition";
export let ncontent;
let message = { msg: "", color: "#d63384" };
let displayMessage = false;
async function handleEditNotice() {
const content = document.querySelector("#notice-content").value;
let formData = new FormData();
formData.append("new-content", content);
try {
const res = await fetch(`/config/notice/`, {
method: "POST",
body: formData,
});
if (res.ok) {
let text = await res.text();
popMessage(text, "#048109");
} else {
let text = await res.text();
throw new Error("Response Code " + res.status + "-> " + text);
}
} catch (err) {
popMessage(err, "#d63384");
}
}
function popMessage(response, rescolor) {
message = { msg: response, color: rescolor };
displayMessage = true;
setTimeout(function () {
displayMessage = false;
}, 3500);
}
</script>

<Col>
<Card class="h-100">
<CardBody>
<CardTitle class="mb-3">Edit Notice Shown On Homepage</CardTitle>
<p>Empty content ("No Content.") hides notice card on homepage.</p>
<div class="input-group mb-3">
<input
type="text"
class="form-control"
placeholder="No Content."
value={ncontent}
id="notice-content"
/>

<!-- PreventDefault on Sveltestrap-Button more complex to achieve than just use good ol' html button -->
<!-- see: https://stackoverflow.com/questions/69630422/svelte-how-to-use-event-modifiers-in-my-own-components -->
<button
class="btn btn-primary"
type="button"
id="edit-notice-button"
on:click|preventDefault={handleEditNotice}>Edit Notice</button
>
</div>
<p>
{#if displayMessage}<b
><code style="color: {message.color};" out:fade
>Update: {message.msg}</code
></b
>{/if}
</p>
</CardBody>
</Card>
</Col>
1 change: 1 addition & 0 deletions web/templates/config.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
const filterPresets = {{ .FilterPresets }};
const clusterCockpitConfig = {{ .Config }};
const resampleConfig = {{ .Resampling }};
const ncontent = {{ .Infos.ncontent }};
</script>
<script src='/build/config.js'></script>
{{end}}

0 comments on commit 00a5786

Please sign in to comment.