feature: Better guest handling (#472)
Some checks failed
Build Snapshot / build-snapshot (push) Has been cancelled
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Codestyle checks / codestyle (push) Has been cancelled
DevSkim / DevSkim (push) Has been cancelled

* feature: Better guest handling

* bugfix: Better handling of requiring guests to login
This commit is contained in:
James Read
2024-11-09 23:27:09 +00:00
committed by GitHub
parent 344df3739d
commit 13e48dded2
8 changed files with 47 additions and 20 deletions

View File

@@ -33,6 +33,10 @@ type AuthenticatedUser struct {
acls []string
}
func (u *AuthenticatedUser) IsGuest() bool {
return u.Username == "guest" && u.Provider == "system"
}
func logAclNotMatched(cfg *config.Config, aclFunction string, user *AuthenticatedUser, action *config.Action, acl *config.AccessControlList) {
if cfg.LogDebugOptions.AclNotMatched {
log.WithFields(log.Fields{
@@ -162,6 +166,7 @@ func UserFromContext(ctx context.Context, cfg *config.Config) *AuthenticatedUser
"username": ret.Username,
"usergroup": ret.Usergroup,
"provider": ret.Provider,
"acls": ret.acls,
}).Debugf("UserFromContext")
return ret

View File

@@ -117,7 +117,7 @@ type Config struct {
AuthHttpHeaderUserGroup string
AuthLocalUsers AuthLocalUsersConfig
AuthLoginUrl string
AuthAllowGuest bool
AuthRequireGuestsToLogin bool
AuthOAuth2RedirectURL string
AuthOAuth2Providers map[string]*OAuth2Provider
DefaultPermissions PermissionsList
@@ -214,7 +214,7 @@ func DefaultConfigWithBasePort(basePort int) *Config {
config.DefaultPermissions.Logs = true
config.AuthJwtClaimUsername = "name"
config.AuthJwtClaimUserGroup = "group"
config.AuthAllowGuest = true
config.AuthRequireGuestsToLogin = false
config.WebUIDir = "./webui"
config.CronSupportForSeconds = false
config.SectionNavigationStyle = "sidebar"

View File

@@ -36,6 +36,14 @@ func Reload(cfg *Config) {
os.Exit(1)
}
if cfg.AuthRequireGuestsToLogin {
log.Infof("AuthRequireGuestsToLogin is enabled. All defaultPermissions will be set to false")
cfg.DefaultPermissions.View = false
cfg.DefaultPermissions.Exec = false
cfg.DefaultPermissions.Logs = false
}
metricConfigReloadedCount.Inc()
metricConfigActionCount.Set(float64(len(cfg.Actions)))

View File

@@ -296,6 +296,10 @@ func (api *oliveTinAPI) Logout(ctx ctx.Context, req *pb.LogoutRequest) (*httpbod
func (api *oliveTinAPI) GetDashboardComponents(ctx ctx.Context, req *pb.GetDashboardComponentsRequest) (*pb.GetDashboardComponentsResponse, error) {
user := acl.UserFromContext(ctx, cfg)
if user.IsGuest() && cfg.AuthRequireGuestsToLogin {
return nil, status.Errorf(codes.PermissionDenied, "Guests are not allowed to access the dashboard.")
}
res := buildDashboardResponse(api.executor, cfg, user)
if len(res.Actions) == 0 {
@@ -306,13 +310,6 @@ func (api *oliveTinAPI) GetDashboardComponents(ctx ctx.Context, req *pb.GetDashb
dashboardCfgToPb(res, cfg.Dashboards, cfg)
res.AuthenticatedUser = user.Username
res.AuthenticatedUserProvider = user.Provider
if res.AuthenticatedUser == "guest" && !cfg.AuthAllowGuest {
return nil, status.Errorf(codes.PermissionDenied, "Unauthenticated")
}
return res, nil
}

View File

@@ -10,7 +10,10 @@ import (
)
func buildDashboardResponse(ex *executor.Executor, cfg *config.Config, user *acl.AuthenticatedUser) *pb.GetDashboardComponentsResponse {
res := &pb.GetDashboardComponentsResponse{}
res := &pb.GetDashboardComponentsResponse{
AuthenticatedUser: user.Username,
AuthenticatedUserProvider: user.Provider,
}
ex.MapActionIdToBindingLock.RLock()

View File

@@ -164,7 +164,7 @@
<section id = "content-login" title = "Login" hidden>
<div class = "flex-col">
<form class = "box-shadow padded-content border-radius" id = "local-user-login">
<p class = "login-disabled">Login with OAuth or Local users is not enabled on this server.</p>
<p class = "login-disabled">This server is not configured with either OAuth, or local users, so you cannot login.</p>
<div class = "login-oauth2" hidden>
<h2>OAuth Login</h2>

View File

@@ -65,25 +65,38 @@ export function initMarshaller () {
window.addEventListener('EventOutputChunk', onOutputChunk)
}
export function marshalDashboardComponentsJsonToHtml (json) {
marshalActionsJsonToHtml(json)
marshalDashboardStructureToHtml(json)
document.getElementById('username').innerText = json.authenticatedUser
function setUsername (username, provider) {
document.getElementById('username').innerText = username
document.getElementById('username').setAttribute('title', provider)
if (window.settings.AuthLocalLogin || window.settings.AuthOAuth2Providers !== null) {
if (json.authenticatedUser === 'guest') {
if (username === 'guest') {
document.getElementById('link-login').hidden = false
document.getElementById('link-logout').hidden = true
} else {
document.getElementById('link-login').hidden = true
if (json.authenticatedUserProvider === 'local' || json.authenticatedUserProvider === 'oauth2') {
if (provider === 'local' || provider === 'oauth2') {
document.getElementById('link-logout').hidden = false
}
}
}
}
document.getElementById('username').setAttribute('title', json.authenticatedUserProvider)
export function marshalDashboardComponentsJsonToHtml (json) {
if (json == null) { // eg: HTTP 403
setUsername('guest', 'system')
if (window.settings.AuthLoginUrl !== '') {
window.location = window.settings.AuthLoginUrl
} else {
showSection('/login')
}
} else {
setUsername(json.authenticatedUser, json.authenticatedUserProvider)
marshalActionsJsonToHtml(json)
marshalDashboardStructureToHtml(json)
}
document.body.setAttribute('initial-marshal-complete', 'true')

View File

@@ -61,8 +61,9 @@ function fetchGetDashboardComponents () {
cors: 'cors'
}).then(res => {
if (!res.ok && res.status === 403) {
window.location.href = window.settings.AuthLoginUrl
return null
}
return res.json()
}).then(res => {
if (!window.restAvailable) {