mirror of
https://github.com/h44z/wg-portal.git
synced 2025-10-07 00:46:18 +00:00
Compare commits
2 Commits
fix_interf
...
peer_state
Author | SHA1 | Date | |
---|---|---|---|
|
1d7dd26290 | ||
|
3c72a26e91 |
@@ -50,7 +50,7 @@ COPY --from=builder /build/dist/wg-portal /
|
||||
######
|
||||
# Final image
|
||||
######
|
||||
FROM alpine:3.22
|
||||
FROM alpine:3.19
|
||||
# Install OS-level dependencies
|
||||
RUN apk add --no-cache bash curl iptables nftables openresolv wireguard-tools
|
||||
# Setup timezone
|
||||
|
@@ -76,7 +76,6 @@ auth:
|
||||
webauthn:
|
||||
enabled: true
|
||||
min_password_length: 16
|
||||
hide_login_form: false
|
||||
|
||||
web:
|
||||
listening_address: :8888
|
||||
@@ -355,12 +354,6 @@ Some core authentication options are shared across all providers, while others a
|
||||
The default admin password strength is also enforced by this setting.
|
||||
- **Important:** The password should be strong and secure. It is recommended to use a password with at least 16 characters, including uppercase and lowercase letters, numbers, and special characters.
|
||||
|
||||
### `hide_login_form`
|
||||
- **Default:** `false`
|
||||
- **Description:** If `true`, the login form is hidden and only the OIDC, OAuth, LDAP, or WebAuthn providers are shown. This is useful if you want to enforce a specific authentication method.
|
||||
If no social login providers are configured, the login form is always shown, regardless of this setting.
|
||||
- **Important:** You can still access the login form by adding the `?all` query parameter to the login URL (e.g. https://wg.portal/#/login?all).
|
||||
|
||||
---
|
||||
|
||||
### OIDC
|
||||
|
@@ -16,10 +16,7 @@ const password = ref("")
|
||||
const usernameInvalid = computed(() => username.value === "")
|
||||
const passwordInvalid = computed(() => password.value === "")
|
||||
const disableLoginBtn = computed(() => username.value === "" || password.value === "" || loggingIn.value)
|
||||
const showLoginForm = computed(() => {
|
||||
console.log(router.currentRoute.value.query)
|
||||
return settings.Setting('LoginFormVisible') || router.currentRoute.value.query.hasOwnProperty('all');
|
||||
});
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
await settings.LoadSettings()
|
||||
@@ -101,7 +98,7 @@ const externalLogin = function (provider) {
|
||||
</div></div>
|
||||
<div class="card-body">
|
||||
<form method="post">
|
||||
<fieldset v-if="showLoginForm">
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="inputUsername">{{ $t('login.username.label') }}</label>
|
||||
<div class="input-group mb-3">
|
||||
@@ -121,40 +118,19 @@ const externalLogin = function (provider) {
|
||||
</div>
|
||||
|
||||
<div class="row mt-5 mb-2">
|
||||
<div class="col-sm-4 col-xs-12">
|
||||
<button :disabled="disableLoginBtn" class="btn btn-primary mb-2" type="submit" @click.prevent="login">
|
||||
<div class="col-lg-4">
|
||||
<button :disabled="disableLoginBtn" class="btn btn-primary" type="submit" @click.prevent="login">
|
||||
{{ $t('login.button') }} <div v-if="loggingIn" class="d-inline"><i class="ms-2 fa-solid fa-circle-notch fa-spin"></i></div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-8 col-xs-12 text-sm-end">
|
||||
<div class="col-lg-8 mb-2 text-end">
|
||||
<button v-if="settings.Setting('WebAuthnEnabled')" class="btn btn-primary" type="submit" @click.prevent="loginWebAuthn">
|
||||
{{ $t('login.button-webauthn') }} <div v-if="loggingIn" class="d-inline"><i class="ms-2 fa-solid fa-circle-notch fa-spin"></i></div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4 d-flex">
|
||||
<div class="col-lg-12 d-flex mb-2">
|
||||
<!-- OpenIdConnect / OAUTH providers -->
|
||||
<button v-for="(provider, idx) in auth.LoginProviders" :key="provider.Identifier" :class="{'ms-1':idx > 0}"
|
||||
:disabled="loggingIn" :title="provider.Name" class="btn btn-outline-primary flex-fill"
|
||||
v-html="provider.Name" @click.prevent="externalLogin(provider)"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset v-else>
|
||||
<div class="row mt-1 mb-2" v-if="settings.Setting('WebAuthnEnabled')">
|
||||
<div class="col-lg-12 d-flex mb-2">
|
||||
<button class="btn btn-outline-primary flex-fill" type="submit" @click.prevent="loginWebAuthn">
|
||||
{{ $t('login.button-webauthn') }} <div v-if="loggingIn" class="d-inline"><i class="ms-2 fa-solid fa-circle-notch fa-spin"></i></div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-1 d-flex">
|
||||
<div class="row mt-5 d-flex">
|
||||
<div class="col-lg-12 d-flex mb-2">
|
||||
<!-- OpenIdConnect / OAUTH providers -->
|
||||
<button v-for="(provider, idx) in auth.LoginProviders" :key="provider.Identifier" :class="{'ms-1':idx > 0}"
|
||||
@@ -168,6 +144,7 @@ const externalLogin = function (provider) {
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -2231,9 +2231,6 @@
|
||||
"ApiAdminOnly": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"LoginFormVisible": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"MailLinkOnly": {
|
||||
"type": "boolean"
|
||||
},
|
||||
|
@@ -381,8 +381,6 @@ definitions:
|
||||
properties:
|
||||
ApiAdminOnly:
|
||||
type: boolean
|
||||
LoginFormVisible:
|
||||
type: boolean
|
||||
MailLinkOnly:
|
||||
type: boolean
|
||||
MinPasswordLength:
|
||||
|
@@ -96,13 +96,10 @@ func (e ConfigEndpoint) handleSettingsGet() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
sessionUser := domain.GetUserInfo(r.Context())
|
||||
|
||||
hasSocialLogin := len(e.cfg.Auth.OAuth) > 0 || len(e.cfg.Auth.OpenIDConnect) > 0 || e.cfg.Auth.WebAuthn.Enabled
|
||||
|
||||
// For anonymous users, we return the settings object with minimal information
|
||||
if sessionUser.Id == domain.CtxUnknownUserId || sessionUser.Id == "" {
|
||||
respond.JSON(w, http.StatusOK, model.Settings{
|
||||
WebAuthnEnabled: e.cfg.Auth.WebAuthn.Enabled,
|
||||
LoginFormVisible: !e.cfg.Auth.HideLoginForm || !hasSocialLogin,
|
||||
WebAuthnEnabled: e.cfg.Auth.WebAuthn.Enabled,
|
||||
})
|
||||
} else {
|
||||
respond.JSON(w, http.StatusOK, model.Settings{
|
||||
@@ -112,7 +109,6 @@ func (e ConfigEndpoint) handleSettingsGet() http.HandlerFunc {
|
||||
ApiAdminOnly: e.cfg.Advanced.ApiAdminOnly,
|
||||
WebAuthnEnabled: e.cfg.Auth.WebAuthn.Enabled,
|
||||
MinPasswordLength: e.cfg.Auth.MinPasswordLength,
|
||||
LoginFormVisible: !e.cfg.Auth.HideLoginForm || !hasSocialLogin,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -12,5 +12,4 @@ type Settings struct {
|
||||
ApiAdminOnly bool `json:"ApiAdminOnly"`
|
||||
WebAuthnEnabled bool `json:"WebAuthnEnabled"`
|
||||
MinPasswordLength int `json:"MinPasswordLength"`
|
||||
LoginFormVisible bool `json:"LoginFormVisible"`
|
||||
}
|
||||
|
@@ -71,7 +71,7 @@ func NewMailManager(
|
||||
users UserDatabaseRepo,
|
||||
wg WireguardDatabaseRepo,
|
||||
) (*Manager, error) {
|
||||
tplHandler, err := newTemplateHandler(cfg.Web.ExternalUrl, cfg.Web.SiteTitle)
|
||||
tplHandler, err := newTemplateHandler(cfg.Web.ExternalUrl)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to initialize template handler: %w", err)
|
||||
}
|
||||
|
@@ -17,12 +17,11 @@ var TemplateFiles embed.FS
|
||||
// TemplateHandler is a struct that holds the html and text templates.
|
||||
type TemplateHandler struct {
|
||||
portalUrl string
|
||||
portalName string
|
||||
htmlTemplates *htmlTemplate.Template
|
||||
textTemplates *template.Template
|
||||
}
|
||||
|
||||
func newTemplateHandler(portalUrl, portalName string) (*TemplateHandler, error) {
|
||||
func newTemplateHandler(portalUrl string) (*TemplateHandler, error) {
|
||||
htmlTemplateCache, err := htmlTemplate.New("Html").ParseFS(TemplateFiles, "tpl_files/*.gohtml")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse html template files: %w", err)
|
||||
@@ -35,7 +34,6 @@ func newTemplateHandler(portalUrl, portalName string) (*TemplateHandler, error)
|
||||
|
||||
handler := &TemplateHandler{
|
||||
portalUrl: portalUrl,
|
||||
portalName: portalName,
|
||||
htmlTemplates: htmlTemplateCache,
|
||||
textTemplates: txtTemplateCache,
|
||||
}
|
||||
@@ -83,7 +81,6 @@ func (c TemplateHandler) GetConfigMailWithAttachment(user *domain.User, cfgName,
|
||||
"ConfigFileName": cfgName,
|
||||
"QrcodePngName": qrName,
|
||||
"PortalUrl": c.portalUrl,
|
||||
"PortalName": c.portalName,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to execute template mail_with_attachment.gotpl: %w", err)
|
||||
@@ -94,7 +91,6 @@ func (c TemplateHandler) GetConfigMailWithAttachment(user *domain.User, cfgName,
|
||||
"ConfigFileName": cfgName,
|
||||
"QrcodePngName": qrName,
|
||||
"PortalUrl": c.portalUrl,
|
||||
"PortalName": c.portalName,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to execute template mail_with_attachment.gohtml: %w", err)
|
||||
|
@@ -19,7 +19,7 @@
|
||||
<!--[if !mso]><!-->
|
||||
<link href="https://fonts.googleapis.com/css?family=Muli:400,400i,700,700i" rel="stylesheet" />
|
||||
<!--<![endif]-->
|
||||
<title>{{$.PortalName}}</title>
|
||||
<title>Email Template</title>
|
||||
<!--[if gte mso 9]>
|
||||
<style type="text/css" media="all">
|
||||
sup { font-size: 100% !important; }
|
||||
@@ -143,7 +143,7 @@
|
||||
<td align="left">
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td class="blue-button text-button" style="background:#000000; color:#ffffff; font-family:'Muli', Arial,sans-serif; font-size:14px; line-height:18px; padding:12px 30px; text-align:center; border-radius:0px 22px 22px 22px; font-weight:bold;"><a href="https://www.wireguard.com/install" target="_blank" class="link-white" style="color:#ffffff; text-decoration:none;"><span class="link-white" style="color:#ffffff; text-decoration:none;">Download WireGuard VPN Client</span></a></td>
|
||||
<td class="blue-button text-button" style="background:#000000; color:#c1cddc; font-family:'Muli', Arial,sans-serif; font-size:14px; line-height:18px; padding:12px 30px; text-align:center; border-radius:0px 22px 22px 22px; font-weight:bold;"><a href="https://www.wireguard.com/install" target="_blank" class="link-white" style="color:#ffffff; text-decoration:none;"><span class="link-white" style="color:#ffffff; text-decoration:none;">Download WireGuard VPN Client</span></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
@@ -167,10 +167,10 @@
|
||||
<td class="p30-15 bbrr" style="padding: 50px 30px; border-radius:0px 0px 26px 26px;" bgcolor="#ffffff">
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td class="text-footer1 pb10" style="color:#000000; font-family:'Muli', Arial,sans-serif; font-size:16px; line-height:20px; text-align:center; padding-bottom:10px;">This mail was generated by {{$.PortalName}}.</td>
|
||||
<td class="text-footer1 pb10" style="color:#000000; font-family:'Muli', Arial,sans-serif; font-size:16px; line-height:20px; text-align:center; padding-bottom:10px;">This mail was generated using WireGuard Portal.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-footer2" style="color:#000000; font-family:'Muli', Arial,sans-serif; font-size:12px; line-height:26px; text-align:center;"><a href="{{$.PortalUrl}}" target="_blank" rel="noopener noreferrer" class="link" style="color:#000000; text-decoration:none;"><span class="link" style="color:#000000; text-decoration:none;">Visit {{$.PortalName}}</span></a></td>
|
||||
<td class="text-footer2" style="color:#000000; font-family:'Muli', Arial,sans-serif; font-size:12px; line-height:26px; text-align:center;"><a href="{{$.PortalUrl}}" target="_blank" rel="noopener noreferrer" class="link" style="color:#000000; text-decoration:none;"><span class="link" style="color:#000000; text-decoration:none;">Visit WireGuard Portal</span></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
|
@@ -20,5 +20,5 @@ You can download and install the WireGuard VPN client from:
|
||||
https://www.wireguard.com/install/
|
||||
|
||||
|
||||
This mail was generated by {{$.PortalName}}.
|
||||
This mail was generated using WireGuard Portal.
|
||||
{{$.PortalUrl}}
|
@@ -19,7 +19,7 @@
|
||||
<!--[if !mso]><!-->
|
||||
<link href="https://fonts.googleapis.com/css?family=Muli:400,400i,700,700i" rel="stylesheet" />
|
||||
<!--<![endif]-->
|
||||
<title>{{$.PortalName}}</title>
|
||||
<title>Email Template</title>
|
||||
<!--[if gte mso 9]>
|
||||
<style type="text/css" media="all">
|
||||
sup { font-size: 100% !important; }
|
||||
@@ -143,7 +143,7 @@
|
||||
<td align="left">
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td class="blue-button text-button" style="background:#000000; color:#ffffff; font-family:'Muli', Arial,sans-serif; font-size:14px; line-height:18px; padding:12px 30px; text-align:center; border-radius:0px 22px 22px 22px; font-weight:bold;"><a href="https://www.wireguard.com/install" target="_blank" class="link-white" style="color:#ffffff; text-decoration:none;"><span class="link-white" style="color:#ffffff; text-decoration:none;">Download WireGuard VPN Client</span></a></td>
|
||||
<td class="blue-button text-button" style="background:#000000; color:#c1cddc; font-family:'Muli', Arial,sans-serif; font-size:14px; line-height:18px; padding:12px 30px; text-align:center; border-radius:0px 22px 22px 22px; font-weight:bold;"><a href="https://www.wireguard.com/install" target="_blank" class="link-white" style="color:#ffffff; text-decoration:none;"><span class="link-white" style="color:#ffffff; text-decoration:none;">Download WireGuard VPN Client</span></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
@@ -167,10 +167,10 @@
|
||||
<td class="p30-15 bbrr" style="padding: 50px 30px; border-radius:0px 0px 26px 26px;" bgcolor="#ffffff">
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td class="text-footer1 pb10" style="color:#000000; font-family:'Muli', Arial,sans-serif; font-size:16px; line-height:20px; text-align:center; padding-bottom:10px;">This mail was generated by {{$.PortalName}}.</td>
|
||||
<td class="text-footer1 pb10" style="color:#000000; font-family:'Muli', Arial,sans-serif; font-size:16px; line-height:20px; text-align:center; padding-bottom:10px;">This mail was generated using WireGuard Portal.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-footer2" style="color:#000000; font-family:'Muli', Arial,sans-serif; font-size:12px; line-height:26px; text-align:center;"><a href="{{$.PortalUrl}}" target="_blank" rel="noopener noreferrer" class="link" style="color:#000000; text-decoration:none;"><span class="link" style="color:#000000; text-decoration:none;">Visit {{$.PortalName}}</span></a></td>
|
||||
<td class="text-footer2" style="color:#000000; font-family:'Muli', Arial,sans-serif; font-size:12px; line-height:26px; text-align:center;"><a href="{{$.PortalUrl}}" target="_blank" rel="noopener noreferrer" class="link" style="color:#000000; text-decoration:none;"><span class="link" style="color:#000000; text-decoration:none;">Visit WireGuard Portal</span></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
|
@@ -20,5 +20,5 @@ You can download and install the WireGuard VPN client from:
|
||||
https://www.wireguard.com/install/
|
||||
|
||||
|
||||
This mail was generated by {{$.PortalName}}.
|
||||
This mail was generated using WireGuard Portal.
|
||||
{{$.PortalUrl}}
|
@@ -461,7 +461,7 @@ func (m Manager) DeleteInterface(ctx context.Context, id domain.InterfaceIdentif
|
||||
|
||||
physicalInterface, _ := m.wg.GetInterface(ctx, id)
|
||||
|
||||
if err := m.handleInterfacePreSaveHooks(existingInterface, !existingInterface.IsDisabled(), false); err != nil {
|
||||
if err := m.handleInterfacePreSaveHooks(true, existingInterface); err != nil {
|
||||
return fmt.Errorf("pre-delete hooks failed: %w", err)
|
||||
}
|
||||
|
||||
@@ -490,7 +490,7 @@ func (m Manager) DeleteInterface(ctx context.Context, id domain.InterfaceIdentif
|
||||
Table: existingInterface.GetRoutingTable(),
|
||||
})
|
||||
|
||||
if err := m.handleInterfacePostSaveHooks(existingInterface, !existingInterface.IsDisabled(), false); err != nil {
|
||||
if err := m.handleInterfacePostSaveHooks(true, existingInterface); err != nil {
|
||||
return fmt.Errorf("post-delete hooks failed: %w", err)
|
||||
}
|
||||
|
||||
@@ -509,9 +509,9 @@ func (m Manager) saveInterface(ctx context.Context, iface *domain.Interface) (
|
||||
return nil, fmt.Errorf("interface validation failed: %w", err)
|
||||
}
|
||||
|
||||
oldEnabled, newEnabled := m.getInterfaceStateHistory(ctx, iface)
|
||||
stateChanged := m.hasInterfaceStateChanged(ctx, iface)
|
||||
|
||||
if err := m.handleInterfacePreSaveHooks(iface, oldEnabled, newEnabled); err != nil {
|
||||
if err := m.handleInterfacePreSaveHooks(stateChanged, iface); err != nil {
|
||||
return nil, fmt.Errorf("pre-save hooks failed: %w", err)
|
||||
}
|
||||
|
||||
@@ -551,7 +551,7 @@ func (m Manager) saveInterface(ctx context.Context, iface *domain.Interface) (
|
||||
m.bus.Publish(app.TopicRouteUpdate, "interface updated: "+string(iface.Identifier))
|
||||
}
|
||||
|
||||
if err := m.handleInterfacePostSaveHooks(iface, oldEnabled, newEnabled); err != nil {
|
||||
if err := m.handleInterfacePostSaveHooks(stateChanged, iface); err != nil {
|
||||
return nil, fmt.Errorf("post-save hooks failed: %w", err)
|
||||
}
|
||||
|
||||
@@ -566,13 +566,32 @@ func (m Manager) saveInterface(ctx context.Context, iface *domain.Interface) (
|
||||
return iface, nil
|
||||
}
|
||||
|
||||
func (m Manager) getInterfaceStateHistory(ctx context.Context, iface *domain.Interface) (oldEnabled, newEnabled bool) {
|
||||
func (m Manager) hasInterfaceStateChanged(ctx context.Context, iface *domain.Interface) bool {
|
||||
oldInterface, err := m.db.GetInterface(ctx, iface.Identifier)
|
||||
if err != nil {
|
||||
return false, !iface.IsDisabled() // if the interface did not exist, we assume it was not enabled
|
||||
return false
|
||||
}
|
||||
|
||||
return !oldInterface.IsDisabled(), !iface.IsDisabled()
|
||||
if oldInterface.IsDisabled() != iface.IsDisabled() {
|
||||
return true // interface in db has changed
|
||||
}
|
||||
|
||||
wgInterface, err := m.wg.GetInterface(ctx, iface.Identifier)
|
||||
if err != nil {
|
||||
return true // interface might not exist - so we assume that there must be a change
|
||||
}
|
||||
|
||||
// compare physical interface settings
|
||||
if len(wgInterface.Addresses) != len(iface.Addresses) ||
|
||||
wgInterface.Mtu != iface.Mtu ||
|
||||
wgInterface.FirewallMark != iface.FirewallMark ||
|
||||
wgInterface.ListenPort != iface.ListenPort ||
|
||||
wgInterface.PrivateKey != iface.PrivateKey ||
|
||||
wgInterface.PublicKey != iface.PublicKey {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (m Manager) handleInterfacePreSaveActions(iface *domain.Interface) error {
|
||||
@@ -588,14 +607,12 @@ func (m Manager) handleInterfacePreSaveActions(iface *domain.Interface) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m Manager) handleInterfacePreSaveHooks(iface *domain.Interface, oldEnabled, newEnabled bool) error {
|
||||
if oldEnabled == newEnabled {
|
||||
func (m Manager) handleInterfacePreSaveHooks(stateChanged bool, iface *domain.Interface) error {
|
||||
if !stateChanged {
|
||||
return nil // do nothing if state did not change
|
||||
}
|
||||
|
||||
slog.Debug("executing pre-save hooks", "interface", iface.Identifier, "up", newEnabled)
|
||||
|
||||
if newEnabled {
|
||||
if !iface.IsDisabled() {
|
||||
if err := m.quick.ExecuteInterfaceHook(iface.Identifier, iface.PreUp); err != nil {
|
||||
return fmt.Errorf("failed to execute pre-up hook: %w", err)
|
||||
}
|
||||
@@ -607,14 +624,12 @@ func (m Manager) handleInterfacePreSaveHooks(iface *domain.Interface, oldEnabled
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m Manager) handleInterfacePostSaveHooks(iface *domain.Interface, oldEnabled, newEnabled bool) error {
|
||||
if oldEnabled == newEnabled {
|
||||
func (m Manager) handleInterfacePostSaveHooks(stateChanged bool, iface *domain.Interface) error {
|
||||
if !stateChanged {
|
||||
return nil // do nothing if state did not change
|
||||
}
|
||||
|
||||
slog.Debug("executing post-save hooks", "interface", iface.Identifier, "up", newEnabled)
|
||||
|
||||
if newEnabled {
|
||||
if !iface.IsDisabled() {
|
||||
if err := m.quick.ExecuteInterfaceHook(iface.Identifier, iface.PostUp); err != nil {
|
||||
return fmt.Errorf("failed to execute post-up hook: %w", err)
|
||||
}
|
||||
|
@@ -21,9 +21,6 @@ type Auth struct {
|
||||
// MinPasswordLength is the minimum password length for user accounts. This also applies to the admin user.
|
||||
// It is encouraged to set this value to at least 16 characters.
|
||||
MinPasswordLength int `yaml:"min_password_length"`
|
||||
// HideLoginForm specifies whether the login form should be hidden. If no social login providers are configured,
|
||||
// the login form will be shown regardless of this setting.
|
||||
HideLoginForm bool `yaml:"hide_login_form"`
|
||||
}
|
||||
|
||||
// BaseFields contains the basic fields that are used to map user information from the authentication providers.
|
||||
|
@@ -95,9 +95,6 @@ func (c *Config) LogStartupValues() {
|
||||
"oidcProviders", len(c.Auth.OpenIDConnect),
|
||||
"oauthProviders", len(c.Auth.OAuth),
|
||||
"ldapProviders", len(c.Auth.Ldap),
|
||||
"webauthnEnabled", c.Auth.WebAuthn.Enabled,
|
||||
"minPasswordLength", c.Auth.MinPasswordLength,
|
||||
"hideLoginForm", c.Auth.HideLoginForm,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -172,7 +169,6 @@ func defaultConfig() *Config {
|
||||
|
||||
cfg.Auth.WebAuthn.Enabled = true
|
||||
cfg.Auth.MinPasswordLength = 16
|
||||
cfg.Auth.HideLoginForm = false
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
Reference in New Issue
Block a user