3k release (#693)

This commit is contained in:
James Read 2025-11-06 00:44:19 +00:00 committed by GitHub
commit a67b5b4e8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 115 additions and 42 deletions

2
.gitignore vendored
View File

@ -17,3 +17,5 @@ webui/
server.log server.log
OliveTin OliveTin
integration-tests/configs/authRequireGuestsToLogin/sessions.yaml integration-tests/configs/authRequireGuestsToLogin/sessions.yaml
webui
webui.dev

View File

@ -5,21 +5,10 @@
# Listen on all addresses available, port 1337 # Listen on all addresses available, port 1337
listenAddressSingleHTTPFrontend: 0.0.0.0:1337 listenAddressSingleHTTPFrontend: 0.0.0.0:1337
bannerMessage: "This is an early alpha version of OliveTin 3000. Many thanks are broken, many things will change."
bannerCss: "background-color: #b2e4b2; color: black; font-size: small; text-align: center; padding: .6em; border-radius: 0.5em;"
insecureAllowDumpSos: true
insecureAllowDumpVars: true
# Choose from INFO (default), WARN and DEBUG # Choose from INFO (default), WARN and DEBUG
# Docs: https://docs.olivetin.app/advanced_configuration/logs.html
logLevel: "INFO" logLevel: "INFO"
# Checking for updates https://docs.olivetin.app/reference/updateChecks.html
checkForUpdates: false
authLocalUsers:
enabled: true
# Actions are commands that are executed by OliveTin, and normally show up as # Actions are commands that are executed by OliveTin, and normally show up as
# buttons on the WebUI. # buttons on the WebUI.
# #
@ -55,6 +44,7 @@ actions:
# You can also rate-limit actions too. # You can also rate-limit actions too.
- title: date - title: date
shell: date shell: date
id: date
timeout: 6 timeout: 6
icon: clock icon: clock
popupOnStart: execution-button popupOnStart: execution-button
@ -322,3 +312,55 @@ dashboards:
- title: 'Start {{ .CurrentEntity.Names }}' - title: 'Start {{ .CurrentEntity.Names }}'
- title: 'Stop {{ .CurrentEntity.Names }}' - title: 'Stop {{ .CurrentEntity.Names }}'
# Security - Authentication
# This setting effectively enables or disables guests.
# If set to "true", then users will have to login to do anything.
authRequireGuestsToLogin: false
# This form of auth is the simplest to setup - just define users and passwords
# in the config. OliveTin also supports header-based auth, OAuth2,
# and JWT authentication which are documented separately.
#
# Docs: https://docs.olivetin.app/security/local.html
#
# How to get a hashed password:
# Docs: https://docs.olivetin.app/security/local.html#_get_a_argon2id_hashed_password
authLocalUsers:
enabled: true
# users:
# - username: alice
# usergroup: admins
# password: "$argon2id$v=19$m=65536,t=4,p=2$puyxA0s555TSFx7hnFLCXA$PyhLGpZtvpMMvc2DgMWkM8OJMKO55euwV5gm//1iwx4"
# Security - Access Control
# Policies affect the whole app (eg: ability to view the log list).
# Docs: https://docs.olivetin.app/security/acl.html
defaultPolicy:
showDiagnostics: true
showLogList: true
# Permissions affect actions (eg: ability to view a specific log).
# Docs: https://docs.olivetin.app/security/acl.html
defaultPermissions:
view: true
exec: true
logs: true
# OliveTin uses access control lists to match up policy and permissions to users.
# Docs: https://docs.olivetin.app/security/acl.html
accessControlLists:
- name: admin_acl
matchUsergroups: ["admins"]
policy:
showDiagnostics: true
permissions:
view: true
exec: true
logs: true
# OliveTin contains many more configuration options not in this default config.
# Check out docs.olivetin.app for a setting if you feel like you're missing something.

View File

@ -17,7 +17,7 @@
"@xterm/addon-fit": "^0.10.0", "@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0", "@xterm/xterm": "^5.5.0",
"iconify-icon": "^3.0.2", "iconify-icon": "^3.0.2",
"picocrank": "^1.6.4", "picocrank": "^1.8.0",
"unplugin-vue-components": "^30.0.0", "unplugin-vue-components": "^30.0.0",
"vite": "^7.1.12", "vite": "^7.1.12",
"vue-router": "^4.6.3" "vue-router": "^4.6.3"
@ -2362,9 +2362,9 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/picocrank": { "node_modules/picocrank": {
"version": "1.6.4", "version": "1.8.0",
"resolved": "https://registry.npmjs.org/picocrank/-/picocrank-1.6.4.tgz", "resolved": "https://registry.npmjs.org/picocrank/-/picocrank-1.8.0.tgz",
"integrity": "sha512-zD1wnkoUDAXZOUs9zKqS4rqz9mljeqFwM7QWx4ykXJsmH6iOLAIKh2AVlxa384oeXJXIWM9VLiySEnhQZmQmjA==", "integrity": "sha512-YPGmXvw7vvjIcgrAe3io87kZDM+NUa+aiEYxk8CVqBzgI4koXeF+2VEGPHBwknZBBEbJfXsSdnxVwXrLKpWKfw==",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@hugeicons/core-free-icons": "^1.0.16", "@hugeicons/core-free-icons": "^1.0.16",

View File

@ -30,7 +30,7 @@
"@xterm/addon-fit": "^0.10.0", "@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0", "@xterm/xterm": "^5.5.0",
"iconify-icon": "^3.0.2", "iconify-icon": "^3.0.2",
"picocrank": "^1.6.4", "picocrank": "^1.8.0",
"unplugin-vue-components": "^30.0.0", "unplugin-vue-components": "^30.0.0",
"vite": "^7.1.12", "vite": "^7.1.12",
"vue-router": "^4.6.3" "vue-router": "^4.6.3"

View File

@ -1,5 +1,5 @@
<template> <template>
<Header title="OliveTin" :logoUrl="logoUrl" @toggleSidebar="toggleSidebar"> <Header title="OliveTin" :logoUrl="logoUrl" @toggleSidebar="toggleSidebar" :sidebarEnabled="showNavigation">
<template #toolbar> <template #toolbar>
<div id="banner" v-if="bannerMessage" :style="bannerCss"> <div id="banner" v-if="bannerMessage" :style="bannerCss">
<p>{{ bannerMessage }}</p> <p>{{ bannerMessage }}</p>
@ -86,7 +86,9 @@ const initError = ref(false)
const initErrorMessage = ref('') const initErrorMessage = ref('')
function toggleSidebar() { function toggleSidebar() {
if (sidebar.value && showNavigation.value) {
sidebar.value.toggle() sidebar.value.toggle()
}
} }
function updateHeaderFromInit() { function updateHeaderFromInit() {
@ -132,6 +134,7 @@ async function requestInit() {
showLogs.value = initResponse.showLogList showLogs.value = initResponse.showLogList
showDiagnostics.value = initResponse.showDiagnostics showDiagnostics.value = initResponse.showDiagnostics
if (showNavigation.value && sidebar.value) {
for (const rootDashboard of initResponse.rootDashboards) { for (const rootDashboard of initResponse.rootDashboards) {
sidebar.value.addNavigationLink({ sidebar.value.addNavigationLink({
id: rootDashboard, id: rootDashboard,
@ -152,6 +155,7 @@ async function requestInit() {
if (showDiagnostics.value) { if (showDiagnostics.value) {
sidebar.value.addRouterLink('Diagnostics') sidebar.value.addRouterLink('Diagnostics')
} }
}
hasLoaded.value = true; hasLoaded.value = true;
initError.value = false; initError.value = false;

View File

@ -11,8 +11,7 @@ plugins:
- remote: buf.build/bufbuild/es - remote: buf.build/bufbuild/es
out: ../frontend/resources/scripts/gen/ out: ../frontend/resources/scripts/gen/
# - name: swagger # - local: ["go", "run", "github.com/sudorandom/protoc-gen-connect-openapi@latest"]
# out: reports/swagger # out: gen
# - local: protoc-gen-openapiv2 # - local: protoc-gen-openapiv2
# out: reports/openapiv2 # out: reports/openapiv2

View File

@ -60,15 +60,38 @@ func GetAll() *variableBase {
} }
func GetEntities() entitiesByClass { func GetEntities() entitiesByClass {
return contents.Entities rwmutex.RLock()
copiedEntities := make(entitiesByClass, len(contents.Entities))
for entityName, entityInstances := range contents.Entities {
copiedInstances := make(entityInstancesByKey, len(entityInstances))
for key, entity := range entityInstances {
copiedInstances[key] = entity
}
copiedEntities[entityName] = copiedInstances
}
rwmutex.RUnlock()
return copiedEntities
} }
func GetEntityInstances(entityName string) entityInstancesByKey { func GetEntityInstances(entityName string) entityInstancesByKey {
rwmutex.RLock()
defer rwmutex.RUnlock()
if entities, ok := contents.Entities[entityName]; ok { if entities, ok := contents.Entities[entityName]; ok {
return entities copiedInstances := make(entityInstancesByKey, len(entities))
for key, entity := range entities {
copiedInstances[key] = entity
}
return copiedInstances
} }
return nil return make(entityInstancesByKey, 0)
} }
func AddEntity(entityName string, entityKey string, data any) { func AddEntity(entityName string, entityKey string, data any) {

View File

@ -91,7 +91,7 @@ func ParseTemplateWithArgs(source string, ent *Entity, args map[string]string) s
} }
templateVariables := &variableBase{ templateVariables := &variableBase{
OliveTin: contents.OliveTin, OliveTin: GetAll().OliveTin,
Arguments: args, Arguments: args,
CurrentEntity: entdata, CurrentEntity: entdata,
} }
@ -126,5 +126,8 @@ func ParseTemplateBoolWith(source string, ent *Entity) bool {
} }
func ClearEntities(entityType string) { func ClearEntities(entityType string) {
rwmutex.Lock()
defer rwmutex.Unlock()
delete(contents.Entities, entityType) delete(contents.Entities, entityType)
} }