@@ -86,6 +86,11 @@ func apiSignup(app *App, w http.ResponseWriter, r *http.Request) error { | |||||
} | } | ||||
func signup(app *App, w http.ResponseWriter, r *http.Request) (*AuthUser, error) { | func signup(app *App, w http.ResponseWriter, r *http.Request) (*AuthUser, error) { | ||||
if app.cfg.App.DisablePasswordAuth { | |||||
err := ErrDisabledPasswordAuth | |||||
return nil, err | |||||
} | |||||
reqJSON := IsJSON(r) | reqJSON := IsJSON(r) | ||||
// Get params | // Get params | ||||
@@ -395,6 +400,11 @@ func login(app *App, w http.ResponseWriter, r *http.Request) error { | |||||
var err error | var err error | ||||
var signin userCredentials | var signin userCredentials | ||||
if app.cfg.App.DisablePasswordAuth { | |||||
err := ErrDisabledPasswordAuth | |||||
return err | |||||
} | |||||
// Log in with one-time token if one is given | // Log in with one-time token if one is given | ||||
if oneTimeToken != "" { | if oneTimeToken != "" { | ||||
log.Info("Login: Logging user in via token.") | log.Info("Login: Logging user in via token.") | ||||
@@ -243,9 +243,22 @@ func handleViewLanding(app *App, w http.ResponseWriter, r *http.Request) error { | |||||
Content template.HTML | Content template.HTML | ||||
ForcedLanding bool | ForcedLanding bool | ||||
OauthSlack bool | |||||
OauthWriteAs bool | |||||
OauthGitlab bool | |||||
OauthGeneric bool | |||||
OauthGenericDisplayName string | |||||
GitlabDisplayName string | |||||
}{ | }{ | ||||
StaticPage: pageForReq(app, r), | |||||
ForcedLanding: forceLanding, | |||||
StaticPage: pageForReq(app, r), | |||||
ForcedLanding: forceLanding, | |||||
OauthSlack: app.Config().SlackOauth.ClientID != "", | |||||
OauthWriteAs: app.Config().WriteAsOauth.ClientID != "", | |||||
OauthGitlab: app.Config().GitlabOauth.ClientID != "", | |||||
OauthGeneric: app.Config().GenericOauth.ClientID != "", | |||||
OauthGenericDisplayName: config.OrDefaultString(app.Config().GenericOauth.DisplayName, genericOauthDisplayName), | |||||
GitlabDisplayName: config.OrDefaultString(app.Config().GitlabOauth.DisplayName, gitlabDisplayName), | |||||
} | } | ||||
banner, err := getLandingBanner(app) | banner, err := getLandingBanner(app) | ||||
@@ -141,6 +141,9 @@ type ( | |||||
// Check for Updates | // Check for Updates | ||||
UpdateChecks bool `ini:"update_checks"` | UpdateChecks bool `ini:"update_checks"` | ||||
// Disable password authentication if use only Oauth | |||||
DisablePasswordAuth bool `ini:"disable_password_auth"` | |||||
} | } | ||||
// Config holds the complete configuration for running a writefreely instance | // Config holds the complete configuration for running a writefreely instance | ||||
@@ -52,6 +52,8 @@ var ( | |||||
ErrUserNotFoundEmail = impart.HTTPError{http.StatusNotFound, "Please enter your username instead of your email address."} | ErrUserNotFoundEmail = impart.HTTPError{http.StatusNotFound, "Please enter your username instead of your email address."} | ||||
ErrUserSilenced = impart.HTTPError{http.StatusForbidden, "Account is silenced."} | ErrUserSilenced = impart.HTTPError{http.StatusForbidden, "Account is silenced."} | ||||
ErrDisabledPasswordAuth = impart.HTTPError{http.StatusForbidden, "Password authentication is disabled."} | |||||
) | ) | ||||
// Post operation errors | // Post operation errors | ||||
@@ -60,6 +60,11 @@ form dd { | |||||
margin-top: 0; | margin-top: 0; | ||||
max-width: 8em; | max-width: 8em; | ||||
} | } | ||||
#generic-oauth-login { | |||||
box-sizing: border-box; | |||||
font-size: 17px; | |||||
white-space:nowrap; | |||||
} | |||||
</style> | </style> | ||||
{{end}} | {{end}} | ||||
{{define "content"}} | {{define "content"}} | ||||
@@ -73,6 +78,22 @@ form dd { | |||||
<div{{if not .OpenRegistration}} style="padding: 2em 0;"{{end}}> | <div{{if not .OpenRegistration}} style="padding: 2em 0;"{{end}}> | ||||
{{ if .OpenRegistration }} | {{ if .OpenRegistration }} | ||||
{{if .DisablePasswordAuth}} | |||||
{{ if or .OauthSlack .OauthWriteAs .OauthGitlab .OauthGeneric }} | |||||
{{ if .OauthSlack }} | |||||
<div class="row content-container signinbtns signinoauthbtns"><a class="loginbtn" href="/oauth/slack"><img alt="Sign in with Slack" height="40" width="172" src="/img/sign_in_with_slack.png" srcset="/img/sign_in_with_slack.png 1x, /img/sign_in_with_slack@2x.png 2x" /></a></div> | |||||
{{ end }} | |||||
{{ if .OauthWriteAs }} | |||||
<div class="row content-container signinbtns signinoauthbtns"><a class="btn cta loginbtn" id="writeas-login" href="/oauth/write.as">Sign in with <strong>Write.as</strong></a></div> | |||||
{{ end }} | |||||
{{ if .OauthGitlab }} | |||||
<div class="row content-container signinbtns signinoauthbtns"><a class="btn cta loginbtn" id="gitlab-login" href="/oauth/gitlab">Sign in with <strong>{{.GitlabDisplayName}}</strong></a></div> | |||||
{{ end }} | |||||
{{ if .OauthGeneric }} | |||||
<div class="row content-container signinbtns signinoauthbtns"><a class="btn cta loginbtn" id="generic-oauth-login" href="/oauth/generic">Sign in with <strong>{{ .OauthGenericDisplayName }}</strong></a></div> | |||||
{{ end }} | |||||
{{ end }} | |||||
{{ else }} | |||||
{{if .Flashes}}<ul class="errors"> | {{if .Flashes}}<ul class="errors"> | ||||
{{range .Flashes}}<li class="urgent">{{.}}</li>{{end}} | {{range .Flashes}}<li class="urgent">{{.}}</li>{{end}} | ||||
</ul>{{end}} | </ul>{{end}} | ||||
@@ -101,6 +122,7 @@ form dd { | |||||
</dl> | </dl> | ||||
</form> | </form> | ||||
</div> | </div> | ||||
{{end}} | |||||
{{ else }} | {{ else }} | ||||
<p style="font-size: 1.3em; margin: 1rem 0;">Registration is currently closed.</p> | <p style="font-size: 1.3em; margin: 1rem 0;">Registration is currently closed.</p> | ||||
<p>You can always sign up on <a href="https://writefreely.org/instances">another instance</a>.</p> | <p>You can always sign up on <a href="https://writefreely.org/instances">another instance</a>.</p> | ||||
@@ -33,12 +33,15 @@ input{margin-bottom:0.5em;} | |||||
{{ end }} | {{ end }} | ||||
</div> | </div> | ||||
<div class="or"> | |||||
<p>or</p> | |||||
<hr class="short" /> | |||||
</div> | |||||
{{if not .DisablePasswordAuth}} | |||||
<div class="or"> | |||||
<p>or</p> | |||||
<hr class="short" /> | |||||
</div> | |||||
{{end}} | |||||
{{ end }} | {{ end }} | ||||
{{if not .DisablePasswordAuth}} | |||||
<form action="/auth/login" method="post" style="text-align: center;margin-top:1em;" onsubmit="disableSubmit()"> | <form action="/auth/login" method="post" style="text-align: center;margin-top:1em;" onsubmit="disableSubmit()"> | ||||
<input type="text" name="alias" placeholder="Username" value="{{.LoginUsername}}" {{if not .LoginUsername}}autofocus{{end}} /><br /> | <input type="text" name="alias" placeholder="Username" value="{{.LoginUsername}}" {{if not .LoginUsername}}autofocus{{end}} /><br /> | ||||
<input type="password" name="pass" placeholder="Password" {{if .LoginUsername}}autofocus{{end}} /><br /> | <input type="password" name="pass" placeholder="Password" {{if .LoginUsername}}autofocus{{end}} /><br /> | ||||
@@ -48,11 +51,12 @@ input{margin-bottom:0.5em;} | |||||
{{if and (not .SingleUser) .OpenRegistration}}<p style="text-align:center;font-size:0.9em;margin:3em auto;max-width:26em;">{{if .Message}}{{.Message}}{{else}}<em>No account yet?</em> <a href="{{.SignupPath}}">Sign up</a> to start a blog.{{end}}</p>{{end}} | {{if and (not .SingleUser) .OpenRegistration}}<p style="text-align:center;font-size:0.9em;margin:3em auto;max-width:26em;">{{if .Message}}{{.Message}}{{else}}<em>No account yet?</em> <a href="{{.SignupPath}}">Sign up</a> to start a blog.{{end}}</p>{{end}} | ||||
<script type="text/javascript"> | |||||
function disableSubmit() { | |||||
var $btn = document.getElementById("btn-login"); | |||||
$btn.value = "Logging in..."; | |||||
$btn.disabled = true; | |||||
} | |||||
</script> | |||||
<script type="text/javascript"> | |||||
function disableSubmit() { | |||||
var $btn = document.getElementById("btn-login"); | |||||
$btn.value = "Logging in..."; | |||||
$btn.disabled = true; | |||||
} | |||||
</script> | |||||
{{end}} | |||||
{{end}} | {{end}} |
@@ -41,6 +41,7 @@ h3 { font-weight: normal; } | |||||
</form> | </form> | ||||
{{ end }} | {{ end }} | ||||
{{if not .DisablePasswordAuth}} | |||||
<form method="post" action="/api/me/self" autocomplete="false"> | <form method="post" action="/api/me/self" autocomplete="false"> | ||||
<input type="hidden" name="logout" value="{{.IsLogOut}}" /> | <input type="hidden" name="logout" value="{{.IsLogOut}}" /> | ||||
<div class="option"> | <div class="option"> | ||||
@@ -72,6 +73,7 @@ h3 { font-weight: normal; } | |||||
<input type="submit" value="Save changes" tabindex="4" /> | <input type="submit" value="Save changes" tabindex="4" /> | ||||
</div> | </div> | ||||
</form> | </form> | ||||
{{end}} | |||||
{{ if .OauthSection }} | {{ if .OauthSection }} | ||||
<hr /> | <hr /> | ||||