Merge pull request #370 from writeas/oauth-cleanup
OAuth tidy-up and refactor
This commit is contained in:
commit
d8019bba0d
36
account.go
36
account.go
|
@ -304,32 +304,18 @@ func viewLogin(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
|
||||||
p := &struct {
|
p := &struct {
|
||||||
page.StaticPage
|
page.StaticPage
|
||||||
To string
|
*OAuthButtons
|
||||||
Message template.HTML
|
To string
|
||||||
Flashes []template.HTML
|
Message template.HTML
|
||||||
LoginUsername string
|
Flashes []template.HTML
|
||||||
OauthSlack bool
|
LoginUsername string
|
||||||
OauthWriteAs bool
|
|
||||||
OauthGitlab bool
|
|
||||||
GitlabDisplayName string
|
|
||||||
OauthGeneric bool
|
|
||||||
OauthGenericDisplayName string
|
|
||||||
OauthGitea bool
|
|
||||||
GiteaDisplayName string
|
|
||||||
}{
|
}{
|
||||||
pageForReq(app, r),
|
StaticPage: pageForReq(app, r),
|
||||||
r.FormValue("to"),
|
OAuthButtons: NewOAuthButtons(app.Config()),
|
||||||
template.HTML(""),
|
To: r.FormValue("to"),
|
||||||
[]template.HTML{},
|
Message: template.HTML(""),
|
||||||
getTempInfo(app, "login-user", r, w),
|
Flashes: []template.HTML{},
|
||||||
app.Config().SlackOauth.ClientID != "",
|
LoginUsername: getTempInfo(app, "login-user", r, w),
|
||||||
app.Config().WriteAsOauth.ClientID != "",
|
|
||||||
app.Config().GitlabOauth.ClientID != "",
|
|
||||||
config.OrDefaultString(app.Config().GenericOauth.DisplayName, genericOauthDisplayName),
|
|
||||||
app.Config().GenericOauth.ClientID != "",
|
|
||||||
config.OrDefaultString(app.Config().GitlabOauth.DisplayName, gitlabDisplayName),
|
|
||||||
app.Config().GiteaOauth.ClientID != "",
|
|
||||||
config.OrDefaultString(app.Config().GiteaOauth.DisplayName, giteaDisplayName),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if earlyError != "" {
|
if earlyError != "" {
|
||||||
|
|
|
@ -494,7 +494,7 @@ func makeActivityPost(hostName string, p *activitystreams.Person, url string, m
|
||||||
|
|
||||||
r, _ := http.NewRequest("POST", url, bytes.NewBuffer(b))
|
r, _ := http.NewRequest("POST", url, bytes.NewBuffer(b))
|
||||||
r.Header.Add("Content-Type", "application/activity+json")
|
r.Header.Add("Content-Type", "application/activity+json")
|
||||||
r.Header.Set("User-Agent", "Go ("+serverSoftware+"/"+softwareVer+"; +"+hostName+")")
|
r.Header.Set("User-Agent", ServerUserAgent(hostName))
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
h.Write(b)
|
h.Write(b)
|
||||||
r.Header.Add("Digest", "SHA-256="+base64.StdEncoding.EncodeToString(h.Sum(nil)))
|
r.Header.Add("Digest", "SHA-256="+base64.StdEncoding.EncodeToString(h.Sum(nil)))
|
||||||
|
@ -544,7 +544,7 @@ func resolveIRI(hostName, url string) ([]byte, error) {
|
||||||
|
|
||||||
r, _ := http.NewRequest("GET", url, nil)
|
r, _ := http.NewRequest("GET", url, nil)
|
||||||
r.Header.Add("Accept", "application/activity+json")
|
r.Header.Add("Accept", "application/activity+json")
|
||||||
r.Header.Set("User-Agent", "Go ("+serverSoftware+"/"+softwareVer+"; +"+hostName+")")
|
r.Header.Set("User-Agent", ServerUserAgent(hostName))
|
||||||
|
|
||||||
if debugging {
|
if debugging {
|
||||||
dump, err := httputil.DumpRequestOut(r, true)
|
dump, err := httputil.DumpRequestOut(r, true)
|
||||||
|
|
29
app.go
29
app.go
|
@ -238,27 +238,16 @@ func handleViewLanding(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
|
||||||
p := struct {
|
p := struct {
|
||||||
page.StaticPage
|
page.StaticPage
|
||||||
|
*OAuthButtons
|
||||||
Flashes []template.HTML
|
Flashes []template.HTML
|
||||||
Banner template.HTML
|
Banner template.HTML
|
||||||
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),
|
StaticPage: pageForReq(app, r),
|
||||||
ForcedLanding: forceLanding,
|
OAuthButtons: NewOAuthButtons(app.Config()),
|
||||||
OauthSlack: app.Config().SlackOauth.ClientID != "",
|
ForcedLanding: forceLanding,
|
||||||
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)
|
||||||
|
@ -903,3 +892,13 @@ func adminInitDatabase(app *App) error {
|
||||||
log.Info("Done.")
|
log.Info("Done.")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServerUserAgent returns a User-Agent string to use in external requests. The
|
||||||
|
// hostName parameter may be left empty.
|
||||||
|
func ServerUserAgent(hostName string) string {
|
||||||
|
hostUAStr := ""
|
||||||
|
if hostName != "" {
|
||||||
|
hostUAStr = "; +" + hostName
|
||||||
|
}
|
||||||
|
return "Go (" + serverSoftware + "/" + softwareVer + hostUAStr + ")"
|
||||||
|
}
|
||||||
|
|
|
@ -81,6 +81,15 @@ type (
|
||||||
CallbackProxyAPI string `ini:"callback_proxy_api"`
|
CallbackProxyAPI string `ini:"callback_proxy_api"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GiteaOauthCfg struct {
|
||||||
|
ClientID string `ini:"client_id"`
|
||||||
|
ClientSecret string `ini:"client_secret"`
|
||||||
|
Host string `ini:"host"`
|
||||||
|
DisplayName string `ini:"display_name"`
|
||||||
|
CallbackProxy string `ini:"callback_proxy"`
|
||||||
|
CallbackProxyAPI string `ini:"callback_proxy_api"`
|
||||||
|
}
|
||||||
|
|
||||||
SlackOauthCfg struct {
|
SlackOauthCfg struct {
|
||||||
ClientID string `ini:"client_id"`
|
ClientID string `ini:"client_id"`
|
||||||
ClientSecret string `ini:"client_secret"`
|
ClientSecret string `ini:"client_secret"`
|
||||||
|
@ -101,14 +110,6 @@ type (
|
||||||
AuthEndpoint string `ini:"auth_endpoint"`
|
AuthEndpoint string `ini:"auth_endpoint"`
|
||||||
AllowDisconnect bool `ini:"allow_disconnect"`
|
AllowDisconnect bool `ini:"allow_disconnect"`
|
||||||
}
|
}
|
||||||
GiteaOauthCfg struct {
|
|
||||||
ClientID string `ini:"client_id"`
|
|
||||||
ClientSecret string `ini:"client_secret"`
|
|
||||||
Host string `ini:"host"`
|
|
||||||
DisplayName string `ini:"display_name"`
|
|
||||||
CallbackProxy string `ini:"callback_proxy"`
|
|
||||||
CallbackProxyAPI string `ini:"callback_proxy_api"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppCfg holds values that affect how the application functions
|
// AppCfg holds values that affect how the application functions
|
||||||
AppCfg struct {
|
AppCfg struct {
|
||||||
|
@ -165,8 +166,8 @@ type (
|
||||||
SlackOauth SlackOauthCfg `ini:"oauth.slack"`
|
SlackOauth SlackOauthCfg `ini:"oauth.slack"`
|
||||||
WriteAsOauth WriteAsOauthCfg `ini:"oauth.writeas"`
|
WriteAsOauth WriteAsOauthCfg `ini:"oauth.writeas"`
|
||||||
GitlabOauth GitlabOauthCfg `ini:"oauth.gitlab"`
|
GitlabOauth GitlabOauthCfg `ini:"oauth.gitlab"`
|
||||||
GenericOauth GenericOauthCfg `ini:"oauth.generic"`
|
|
||||||
GiteaOauth GiteaOauthCfg `ini:"oauth.gitea"`
|
GiteaOauth GiteaOauthCfg `ini:"oauth.gitea"`
|
||||||
|
GenericOauth GenericOauthCfg `ini:"oauth.generic"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
10
database.go
10
database.go
|
@ -2627,11 +2627,11 @@ func (db *datastore) GetIDForRemoteUser(ctx context.Context, remoteUserID, provi
|
||||||
}
|
}
|
||||||
|
|
||||||
type oauthAccountInfo struct {
|
type oauthAccountInfo struct {
|
||||||
Provider string
|
Provider string
|
||||||
ClientID string
|
ClientID string
|
||||||
RemoteUserID string
|
RemoteUserID string
|
||||||
DisplayName string
|
DisplayName string
|
||||||
AllowDisconnect bool
|
AllowDisconnect bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *datastore) GetOauthAccounts(ctx context.Context, userID int64) ([]oauthAccountInfo, error) {
|
func (db *datastore) GetOauthAccounts(ctx context.Context, userID int64) ([]oauthAccountInfo, error) {
|
||||||
|
|
|
@ -170,14 +170,14 @@ func handleViewInvite(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
|
||||||
p := struct {
|
p := struct {
|
||||||
page.StaticPage
|
page.StaticPage
|
||||||
|
*OAuthButtons
|
||||||
Error string
|
Error string
|
||||||
Flashes []template.HTML
|
Flashes []template.HTML
|
||||||
Invite string
|
Invite string
|
||||||
OAuth *OAuthButtons
|
|
||||||
}{
|
}{
|
||||||
StaticPage: pageForReq(app, r),
|
StaticPage: pageForReq(app, r),
|
||||||
Invite: inviteCode,
|
OAuthButtons: NewOAuthButtons(app.cfg),
|
||||||
OAuth: NewOAuthButtons(app.cfg),
|
Invite: inviteCode,
|
||||||
}
|
}
|
||||||
|
|
||||||
if expired {
|
if expired {
|
||||||
|
|
|
@ -9,18 +9,64 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.row.signinbtns {
|
.row.signinbtns {
|
||||||
justify-content: space-evenly;
|
justify-content: center;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
margin-top: 2em;
|
margin-top: 2em;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
.loginbtn {
|
.loginbtn {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
margin: 0.5em;
|
||||||
|
|
||||||
#writeas-login, #gitlab-login {
|
&.btn {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 1.5em;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&#writeas-login, &#slack-login {
|
||||||
|
img {
|
||||||
|
margin-top: -0.2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&#gitlab-login {
|
||||||
|
background-color: #fc6d26;
|
||||||
|
border-color: #fc6d26;
|
||||||
|
&:hover {
|
||||||
|
background-color: darken(#fc6d26, 5%);
|
||||||
|
border-color: darken(#fc6d26, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&#gitea-login {
|
||||||
|
background-color: #2ecc71;
|
||||||
|
border-color: #2ecc71;
|
||||||
|
&:hover {
|
||||||
|
background-color: #2cc26b;
|
||||||
|
border-color: #2cc26b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&#slack-login, &#gitlab-login, &#gitea-login, &#generic-oauth-login {
|
||||||
|
font-size: 0.86em;
|
||||||
|
font-family: @sansFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
&#slack-login, &#generic-oauth-login {
|
||||||
|
color: @lightTextColor;
|
||||||
|
background-color: @lightNavBG;
|
||||||
|
border-color: @lightNavBorder;
|
||||||
|
&:hover {
|
||||||
|
background-color: @lightNavHoverBG;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
32
oauth.go
32
oauth.go
|
@ -30,19 +30,27 @@ import (
|
||||||
|
|
||||||
// OAuthButtons holds display information for different OAuth providers we support.
|
// OAuthButtons holds display information for different OAuth providers we support.
|
||||||
type OAuthButtons struct {
|
type OAuthButtons struct {
|
||||||
SlackEnabled bool
|
SlackEnabled bool
|
||||||
WriteAsEnabled bool
|
WriteAsEnabled bool
|
||||||
GitLabEnabled bool
|
GitLabEnabled bool
|
||||||
GitLabDisplayName string
|
GitLabDisplayName string
|
||||||
|
GiteaEnabled bool
|
||||||
|
GiteaDisplayName string
|
||||||
|
GenericEnabled bool
|
||||||
|
GenericDisplayName string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOAuthButtons creates a new OAuthButtons struct based on our app configuration.
|
// NewOAuthButtons creates a new OAuthButtons struct based on our app configuration.
|
||||||
func NewOAuthButtons(cfg *config.Config) *OAuthButtons {
|
func NewOAuthButtons(cfg *config.Config) *OAuthButtons {
|
||||||
return &OAuthButtons{
|
return &OAuthButtons{
|
||||||
SlackEnabled: cfg.SlackOauth.ClientID != "",
|
SlackEnabled: cfg.SlackOauth.ClientID != "",
|
||||||
WriteAsEnabled: cfg.WriteAsOauth.ClientID != "",
|
WriteAsEnabled: cfg.WriteAsOauth.ClientID != "",
|
||||||
GitLabEnabled: cfg.GitlabOauth.ClientID != "",
|
GitLabEnabled: cfg.GitlabOauth.ClientID != "",
|
||||||
GitLabDisplayName: config.OrDefaultString(cfg.GitlabOauth.DisplayName, gitlabDisplayName),
|
GitLabDisplayName: config.OrDefaultString(cfg.GitlabOauth.DisplayName, gitlabDisplayName),
|
||||||
|
GiteaEnabled: cfg.GiteaOauth.ClientID != "",
|
||||||
|
GiteaDisplayName: config.OrDefaultString(cfg.GiteaOauth.DisplayName, giteaDisplayName),
|
||||||
|
GenericEnabled: cfg.GenericOauth.ClientID != "",
|
||||||
|
GenericDisplayName: config.OrDefaultString(cfg.GenericOauth.DisplayName, genericOauthDisplayName),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,6 +326,12 @@ func (h oauthHandler) viewOauthCallback(app *App, w http.ResponseWriter, r *http
|
||||||
tokenResponse, err := h.oauthClient.exchangeOauthCode(ctx, code)
|
tokenResponse, err := h.oauthClient.exchangeOauthCode(ctx, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to exchangeOauthCode: %s", err)
|
log.Error("Unable to exchangeOauthCode: %s", err)
|
||||||
|
// TODO: show user friendly message if needed
|
||||||
|
// TODO: show NO message for cases like user pressing "Cancel" on authorize step
|
||||||
|
addSessionFlash(app, w, r, err.Error(), nil)
|
||||||
|
if attachUserID > 0 {
|
||||||
|
return impart.HTTPError{http.StatusFound, "/me/settings"}
|
||||||
|
}
|
||||||
return impart.HTTPError{http.StatusInternalServerError, err.Error()}
|
return impart.HTTPError{http.StatusInternalServerError, err.Error()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +422,7 @@ func (r *callbackProxyClient) register(ctx context.Context, state string) error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
req.Header.Set("User-Agent", "writefreely")
|
req.Header.Set("User-Agent", ServerUserAgent(""))
|
||||||
req.Header.Set("Accept", "application/json")
|
req.Header.Set("Accept", "application/json")
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ func (c genericOauthClient) exchangeOauthCode(ctx context.Context, code string)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.WithContext(ctx)
|
req.WithContext(ctx)
|
||||||
req.Header.Set("User-Agent", "writefreely")
|
req.Header.Set("User-Agent", ServerUserAgent(""))
|
||||||
req.Header.Set("Accept", "application/json")
|
req.Header.Set("Accept", "application/json")
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
req.SetBasicAuth(c.ClientID, c.ClientSecret)
|
req.SetBasicAuth(c.ClientID, c.ClientSecret)
|
||||||
|
@ -91,7 +91,7 @@ func (c genericOauthClient) inspectOauthAccessToken(ctx context.Context, accessT
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.WithContext(ctx)
|
req.WithContext(ctx)
|
||||||
req.Header.Set("User-Agent", "writefreely")
|
req.Header.Set("User-Agent", ServerUserAgent(""))
|
||||||
req.Header.Set("Accept", "application/json")
|
req.Header.Set("Accept", "application/json")
|
||||||
req.Header.Set("Authorization", "Bearer "+accessToken)
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ func (c giteaOauthClient) exchangeOauthCode(ctx context.Context, code string) (*
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.WithContext(ctx)
|
req.WithContext(ctx)
|
||||||
req.Header.Set("User-Agent", "writefreely")
|
req.Header.Set("User-Agent", ServerUserAgent(""))
|
||||||
req.Header.Set("Accept", "application/json")
|
req.Header.Set("Accept", "application/json")
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
req.SetBasicAuth(c.ClientID, c.ClientSecret)
|
req.SetBasicAuth(c.ClientID, c.ClientSecret)
|
||||||
|
@ -91,7 +91,7 @@ func (c giteaOauthClient) inspectOauthAccessToken(ctx context.Context, accessTok
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.WithContext(ctx)
|
req.WithContext(ctx)
|
||||||
req.Header.Set("User-Agent", "writefreely")
|
req.Header.Set("User-Agent", ServerUserAgent(""))
|
||||||
req.Header.Set("Accept", "application/json")
|
req.Header.Set("Accept", "application/json")
|
||||||
req.Header.Set("Authorization", "Bearer "+accessToken)
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ func (c gitlabOauthClient) exchangeOauthCode(ctx context.Context, code string) (
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.WithContext(ctx)
|
req.WithContext(ctx)
|
||||||
req.Header.Set("User-Agent", "writefreely")
|
req.Header.Set("User-Agent", ServerUserAgent(""))
|
||||||
req.Header.Set("Accept", "application/json")
|
req.Header.Set("Accept", "application/json")
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
req.SetBasicAuth(c.ClientID, c.ClientSecret)
|
req.SetBasicAuth(c.ClientID, c.ClientSecret)
|
||||||
|
@ -92,7 +92,7 @@ func (c gitlabOauthClient) inspectOauthAccessToken(ctx context.Context, accessTo
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.WithContext(ctx)
|
req.WithContext(ctx)
|
||||||
req.Header.Set("User-Agent", "writefreely")
|
req.Header.Set("User-Agent", ServerUserAgent(""))
|
||||||
req.Header.Set("Accept", "application/json")
|
req.Header.Set("Accept", "application/json")
|
||||||
req.Header.Set("Authorization", "Bearer "+accessToken)
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ func (c slackOauthClient) exchangeOauthCode(ctx context.Context, code string) (*
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.WithContext(ctx)
|
req.WithContext(ctx)
|
||||||
req.Header.Set("User-Agent", "writefreely")
|
req.Header.Set("User-Agent", ServerUserAgent(""))
|
||||||
req.Header.Set("Accept", "application/json")
|
req.Header.Set("Accept", "application/json")
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
req.SetBasicAuth(c.ClientID, c.ClientSecret)
|
req.SetBasicAuth(c.ClientID, c.ClientSecret)
|
||||||
|
@ -140,7 +140,7 @@ func (c slackOauthClient) inspectOauthAccessToken(ctx context.Context, accessTok
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.WithContext(ctx)
|
req.WithContext(ctx)
|
||||||
req.Header.Set("User-Agent", "writefreely")
|
req.Header.Set("User-Agent", ServerUserAgent(""))
|
||||||
req.Header.Set("Accept", "application/json")
|
req.Header.Set("Accept", "application/json")
|
||||||
req.Header.Set("Authorization", "Bearer "+accessToken)
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ func (c writeAsOauthClient) exchangeOauthCode(ctx context.Context, code string)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.WithContext(ctx)
|
req.WithContext(ctx)
|
||||||
req.Header.Set("User-Agent", "writefreely")
|
req.Header.Set("User-Agent", ServerUserAgent(""))
|
||||||
req.Header.Set("Accept", "application/json")
|
req.Header.Set("Accept", "application/json")
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
req.SetBasicAuth(c.ClientID, c.ClientSecret)
|
req.SetBasicAuth(c.ClientID, c.ClientSecret)
|
||||||
|
@ -91,7 +91,7 @@ func (c writeAsOauthClient) inspectOauthAccessToken(ctx context.Context, accessT
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.WithContext(ctx)
|
req.WithContext(ctx)
|
||||||
req.Header.Set("User-Agent", "writefreely")
|
req.Header.Set("User-Agent", ServerUserAgent(""))
|
||||||
req.Header.Set("Accept", "application/json")
|
req.Header.Set("Accept", "application/json")
|
||||||
req.Header.Set("Authorization", "Bearer "+accessToken)
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
||||||
|
|
||||||
|
|
|
@ -60,10 +60,8 @@ form dd {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
max-width: 8em;
|
max-width: 8em;
|
||||||
}
|
}
|
||||||
#generic-oauth-login {
|
.or {
|
||||||
box-sizing: border-box;
|
margin-bottom: 2.5em !important;
|
||||||
font-size: 17px;
|
|
||||||
white-space:nowrap;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -78,20 +76,7 @@ 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 or .OauthSlack .OauthWriteAs .OauthGitlab .OauthGeneric }}
|
{{template "oauth-buttons" .}}
|
||||||
{{ 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 }}
|
|
||||||
{{if not .DisablePasswordAuth}}
|
{{if not .DisablePasswordAuth}}
|
||||||
{{if .Flashes}}<ul class="errors">
|
{{if .Flashes}}<ul class="errors">
|
||||||
{{range .Flashes}}<li class="urgent">{{.}}</li>{{end}}
|
{{range .Flashes}}<li class="urgent">{{.}}</li>{{end}}
|
||||||
|
|
|
@ -3,10 +3,6 @@
|
||||||
<meta itemprop="description" content="Log in to {{.SiteName}}.">
|
<meta itemprop="description" content="Log in to {{.SiteName}}.">
|
||||||
<style>
|
<style>
|
||||||
input{margin-bottom:0.5em;}
|
input{margin-bottom:0.5em;}
|
||||||
#generic-oauth-login {
|
|
||||||
box-sizing: border-box;
|
|
||||||
font-size: 17px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
|
@ -17,32 +13,7 @@ input{margin-bottom:0.5em;}
|
||||||
{{range .Flashes}}<li class="urgent">{{.}}</li>{{end}}
|
{{range .Flashes}}<li class="urgent">{{.}}</li>{{end}}
|
||||||
</ul>{{end}}
|
</ul>{{end}}
|
||||||
|
|
||||||
{{ if or .OauthSlack .OauthWriteAs .OauthGitlab .OauthGeneric .OauthGitea }}
|
{{template "oauth-buttons" .}}
|
||||||
<div class="row content-container signinbtns">
|
|
||||||
{{ if .OauthSlack }}
|
|
||||||
<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>
|
|
||||||
{{ end }}
|
|
||||||
{{ if .OauthWriteAs }}
|
|
||||||
<a class="btn cta loginbtn" id="writeas-login" href="/oauth/write.as">Sign in with <strong>Write.as</strong></a>
|
|
||||||
{{ end }}
|
|
||||||
{{ if .OauthGitlab }}
|
|
||||||
<a class="btn cta loginbtn" id="gitlab-login" href="/oauth/gitlab">Sign in with <strong>{{.GitlabDisplayName}}</strong></a>
|
|
||||||
{{ end }}
|
|
||||||
{{ if .OauthGeneric }}
|
|
||||||
<a class="btn cta loginbtn" id="generic-oauth-login" href="/oauth/generic">Sign in with <strong>{{ .OauthGenericDisplayName }}</strong></a>
|
|
||||||
{{ end }}
|
|
||||||
{{ if .OauthGitea }}
|
|
||||||
<a class="btn cta loginbtn" id="gitea-login" href="/oauth/gitea">Sign in with <strong>{{.GiteaDisplayName}}</strong></a>
|
|
||||||
{{ end }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{if not .DisablePasswordAuth}}
|
|
||||||
<div class="or">
|
|
||||||
<p>or</p>
|
|
||||||
<hr class="short" />
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
{{if not .DisablePasswordAuth}}
|
{{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()">
|
||||||
|
|
|
@ -70,25 +70,9 @@ form dd {
|
||||||
</ul>{{end}}
|
</ul>{{end}}
|
||||||
|
|
||||||
<div id="billing">
|
<div id="billing">
|
||||||
{{ if or .OAuth.SlackEnabled .OAuth.WriteAsEnabled .OAuth.GitLabEnabled }}
|
{{template "oauth-buttons" .}}
|
||||||
<div class="row content-container signinbtns">
|
|
||||||
{{ if .OAuth.SlackEnabled }}
|
|
||||||
<a class="loginbtn" href="/oauth/slack{{if .Invite}}?invite_code={{.Invite}}{{end}}"><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>
|
|
||||||
{{ end }}
|
|
||||||
{{ if .OAuth.WriteAsEnabled }}
|
|
||||||
<a class="btn cta loginbtn" id="writeas-login" href="/oauth/write.as{{if .Invite}}?invite_code={{.Invite}}{{end}}">Sign in with <strong>Write.as</strong></a>
|
|
||||||
{{ end }}
|
|
||||||
{{ if .OAuth.GitLabEnabled }}
|
|
||||||
<a class="btn cta loginbtn" id="gitlab-login" href="/oauth/gitlab{{if .Invite}}?invite_code={{.Invite}}{{end}}">Sign in with <strong>{{.OAuth.GitLabDisplayName}}</strong></a>
|
|
||||||
{{ end }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="or">
|
|
||||||
<p>or</p>
|
|
||||||
<hr class="short" />
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
|
{{if not .DisablePasswordAuth}}
|
||||||
<form action="/auth/signup" method="POST" id="signup-form" onsubmit="return signup()">
|
<form action="/auth/signup" method="POST" id="signup-form" onsubmit="return signup()">
|
||||||
<input type="hidden" name="invite_code" value="{{.Invite}}" />
|
<input type="hidden" name="invite_code" value="{{.Invite}}" />
|
||||||
<dl class="billing">
|
<dl class="billing">
|
||||||
|
@ -112,6 +96,7 @@ form dd {
|
||||||
</dt>
|
</dt>
|
||||||
</dl>
|
</dl>
|
||||||
</form>
|
</form>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
10
templates.go
10
templates.go
|
@ -85,12 +85,18 @@ func initPage(parentDir, path, key string) {
|
||||||
log.Info(" [%s] %s", key, path)
|
log.Info(" [%s] %s", key, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
pages[key] = template.Must(template.New("").Funcs(funcMap).ParseFiles(
|
files := []string{
|
||||||
path,
|
path,
|
||||||
filepath.Join(parentDir, templatesDir, "include", "footer.tmpl"),
|
filepath.Join(parentDir, templatesDir, "include", "footer.tmpl"),
|
||||||
filepath.Join(parentDir, templatesDir, "base.tmpl"),
|
filepath.Join(parentDir, templatesDir, "base.tmpl"),
|
||||||
filepath.Join(parentDir, templatesDir, "user", "include", "silenced.tmpl"),
|
filepath.Join(parentDir, templatesDir, "user", "include", "silenced.tmpl"),
|
||||||
))
|
}
|
||||||
|
|
||||||
|
if key == "login.tmpl" || key == "landing.tmpl" || key == "signup.tmpl" {
|
||||||
|
files = append(files, filepath.Join(parentDir, templatesDir, "include", "oauth.tmpl"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pages[key] = template.Must(template.New("").Funcs(funcMap).ParseFiles(files...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func initUserPage(parentDir, path, key string) {
|
func initUserPage(parentDir, path, key string) {
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
{{define "oauth-buttons"}}
|
||||||
|
{{ if or .SlackEnabled .WriteAsEnabled .GitLabEnabled .GiteaEnabled .GenericEnabled }}
|
||||||
|
<div class="row content-container signinbtns">
|
||||||
|
{{ if .SlackEnabled }}
|
||||||
|
<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>
|
||||||
|
{{ end }}
|
||||||
|
{{ if .WriteAsEnabled }}
|
||||||
|
<a class="btn cta loginbtn" id="writeas-login" href="/oauth/write.as">
|
||||||
|
<img src="/img/mark/writeas-white.png" />
|
||||||
|
Sign in with <strong>Write.as</strong>
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
{{ if .GitLabEnabled }}
|
||||||
|
<a class="btn cta loginbtn" id="gitlab-login" href="/oauth/gitlab">
|
||||||
|
<img src="/img/mark/gitlab.png" />
|
||||||
|
Sign in with <strong>{{.GitLabDisplayName}}</strong>
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
{{ if .GiteaEnabled }}
|
||||||
|
<a class="btn cta loginbtn" id="gitea-login" href="/oauth/gitea">
|
||||||
|
<img src="/img/mark/gitea.png" />
|
||||||
|
Sign in with <strong>{{.GiteaDisplayName}}</strong>
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
{{ if .GenericEnabled }}
|
||||||
|
<a class="btn cta loginbtn" id="generic-oauth-login" href="/oauth/generic">Sign in with <strong>{{.GenericDisplayName}}</strong></a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{if not .DisablePasswordAuth}}
|
||||||
|
<div class="or">
|
||||||
|
<p>or</p>
|
||||||
|
<hr class="short" />
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
{{ end }}
|
||||||
|
{{end}}
|
|
@ -75,18 +75,18 @@ h3 { font-weight: normal; }
|
||||||
</form>
|
</form>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{ if .OauthSection }}
|
{{ if .OauthSection }}
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
{{ if .OauthAccounts }}
|
{{ if .OauthAccounts }}
|
||||||
<div class="option">
|
<div class="option">
|
||||||
<h2>Linked Accounts</h2>
|
<h2>Linked Accounts</h2>
|
||||||
<p>These are your linked external accounts.</p>
|
<p>These are your linked external accounts.</p>
|
||||||
{{ range $oauth_account := .OauthAccounts }}
|
{{ range $oauth_account := .OauthAccounts }}
|
||||||
<form method="post" action="/api/me/oauth/remove" autocomplete="false">
|
<form method="post" action="/api/me/oauth/remove" autocomplete="false">
|
||||||
<input type="hidden" name="provider" value="{{ $oauth_account.Provider }}" />
|
<input type="hidden" name="provider" value="{{ $oauth_account.Provider }}" />
|
||||||
<input type="hidden" name="client_id" value="{{ $oauth_account.ClientID }}" />
|
<input type="hidden" name="client_id" value="{{ $oauth_account.ClientID }}" />
|
||||||
<input type="hidden" name="remote_user_id" value="{{ $oauth_account.RemoteUserID }}" />
|
<input type="hidden" name="remote_user_id" value="{{ $oauth_account.RemoteUserID }}" />
|
||||||
<div class="section oauth-provider">
|
<div class="section oauth-provider">
|
||||||
{{ if $oauth_account.DisplayName}}
|
{{ if $oauth_account.DisplayName}}
|
||||||
{{ if $oauth_account.AllowDisconnect}}
|
{{ if $oauth_account.AllowDisconnect}}
|
||||||
|
@ -99,58 +99,58 @@ h3 { font-weight: normal; }
|
||||||
<input type="submit" value="Remove {{ $oauth_account.Provider | title }}" />
|
<input type="submit" value="Remove {{ $oauth_account.Provider | title }}" />
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ if or .OauthSlack .OauthWriteAs .OauthGitLab .OauthGeneric .OauthGitea }}
|
{{ if or .OauthSlack .OauthWriteAs .OauthGitLab .OauthGeneric .OauthGitea }}
|
||||||
<div class="option">
|
<div class="option">
|
||||||
<h2>Link External Accounts</h2>
|
<h2>Link External Accounts</h2>
|
||||||
<p>Connect additional accounts to enable logging in with those providers, instead of using your username and password.</p>
|
<p>Connect additional accounts to enable logging in with those providers, instead of using your username and password.</p>
|
||||||
<div class="row">
|
<div class="row signinbtns">
|
||||||
{{ if .OauthWriteAs }}
|
{{ if .OauthWriteAs }}
|
||||||
<div class="section oauth-provider">
|
<div class="section oauth-provider">
|
||||||
<img src="/img/mark/writeas.png" alt="Write.as" />
|
|
||||||
<a class="btn cta loginbtn" id="writeas-login" href="/oauth/write.as?attach=t">
|
<a class="btn cta loginbtn" id="writeas-login" href="/oauth/write.as?attach=t">
|
||||||
|
<img src="/img/mark/writeas-white.png" alt="Write.as" />
|
||||||
Link <strong>Write.as</strong>
|
Link <strong>Write.as</strong>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ if .OauthSlack }}
|
{{ if .OauthSlack }}
|
||||||
<div class="section oauth-provider">
|
<div class="section oauth-provider">
|
||||||
<img src="/img/mark/slack.png" alt="Slack" />
|
<a class="btn cta loginbtn" id="slack-login" href="/oauth/slack?attach=t">
|
||||||
<a class="btn cta loginbtn" href="/oauth/slack?attach=t">
|
<img src="/img/mark/slack.png" alt="Slack" />
|
||||||
Link <strong>Slack</strong>
|
Link <strong>Slack</strong>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ if .OauthGitLab }}
|
{{ if .OauthGitLab }}
|
||||||
<div class="section oauth-provider">
|
<div class="section oauth-provider">
|
||||||
<img src="/img/mark/gitlab.png" alt="GitLab" />
|
|
||||||
<a class="btn cta loginbtn" id="gitlab-login" href="/oauth/gitlab?attach=t">
|
<a class="btn cta loginbtn" id="gitlab-login" href="/oauth/gitlab?attach=t">
|
||||||
|
<img src="/img/mark/gitlab.png" alt="GitLab" />
|
||||||
Link <strong>{{.GitLabDisplayName}}</strong>
|
Link <strong>{{.GitLabDisplayName}}</strong>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ if .OauthGitea }}
|
{{ if .OauthGitea }}
|
||||||
<div class="section oauth-provider">
|
<div class="section oauth-provider">
|
||||||
<img src="/img/mark/gitea.png" alt="Gitea" />
|
|
||||||
<a class="btn cta loginbtn" id="gitea-login" href="/oauth/gitea?attach=t">
|
<a class="btn cta loginbtn" id="gitea-login" href="/oauth/gitea?attach=t">
|
||||||
|
<img src="/img/mark/gitea.png" alt="Gitea" />
|
||||||
Link <strong>{{.GiteaDisplayName}}</strong>
|
Link <strong>{{.GiteaDisplayName}}</strong>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
{{ if .OauthGeneric }}
|
||||||
{{ if .OauthGeneric }}
|
<div class="section oauth-provider">
|
||||||
<div class="row">
|
<a class="btn cta loginbtn" id="generic-oauth-login" href="/oauth/generic?attach=t">
|
||||||
<div class="section oauth-provider">
|
Link <strong>{{ .OauthGenericDisplayName }}</strong>
|
||||||
<p><a class="btn cta loginbtn" id="generic-oauth-login" href="/oauth/generic?attach=t">Link <strong>{{ .OauthGenericDisplayName }}</strong></a></p>
|
</a>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
Loading…
Reference in New Issue