linting + organizing

This commit is contained in:
tsmethurst
2021-04-20 18:14:23 +02:00
parent 32c5fd987a
commit dafc3b5b92
60 changed files with 746 additions and 390 deletions

View File

@ -1,5 +0,0 @@
# auth
This package provides uses the [GoToSocial oauth2](https://github.com/gotosocial/oauth2) module (forked from [go-oauth2](https://github.com/go-oauth2/oauth2)) to provide [oauth2](https://www.oauth.com/) functionality to the GoToSocial client API.
It also provides a handler/middleware for attaching to the Gin engine for validating authenticated users.

View File

@ -16,12 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Package auth is a module that provides oauth functionality to a router.
// It adds the following paths:
// /auth/sign_in
// /oauth/token
// /oauth/authorize
// It also includes the oauthTokenMiddleware, which can be attached to a router to authenticate every request by Bearer token.
package auth
import (
@ -37,12 +31,16 @@ import (
)
const (
authSignInPath = "/auth/sign_in"
oauthTokenPath = "/oauth/token"
oauthAuthorizePath = "/oauth/authorize"
// AuthSignInPath is the API path for users to sign in through
AuthSignInPath = "/auth/sign_in"
// OauthTokenPath is the API path to use for granting token requests to users with valid credentials
OauthTokenPath = "/oauth/token"
// OauthAuthorizePath is the API path for authorization requests (eg., authorize this app to act on my behalf as a user)
OauthAuthorizePath = "/oauth/authorize"
)
type authModule struct {
// Module implements the ClientAPIModule interface for
type Module struct {
server oauth.Server
db db.DB
log *logrus.Logger
@ -50,7 +48,7 @@ type authModule struct {
// New returns a new auth module
func New(srv oauth.Server, db db.DB, log *logrus.Logger) apimodule.ClientAPIModule {
return &authModule{
return &Module{
server: srv,
db: db,
log: log,
@ -58,20 +56,21 @@ func New(srv oauth.Server, db db.DB, log *logrus.Logger) apimodule.ClientAPIModu
}
// Route satisfies the RESTAPIModule interface
func (m *authModule) Route(s router.Router) error {
s.AttachHandler(http.MethodGet, authSignInPath, m.signInGETHandler)
s.AttachHandler(http.MethodPost, authSignInPath, m.signInPOSTHandler)
func (m *Module) Route(s router.Router) error {
s.AttachHandler(http.MethodGet, AuthSignInPath, m.SignInGETHandler)
s.AttachHandler(http.MethodPost, AuthSignInPath, m.SignInPOSTHandler)
s.AttachHandler(http.MethodPost, oauthTokenPath, m.tokenPOSTHandler)
s.AttachHandler(http.MethodPost, OauthTokenPath, m.TokenPOSTHandler)
s.AttachHandler(http.MethodGet, oauthAuthorizePath, m.authorizeGETHandler)
s.AttachHandler(http.MethodPost, oauthAuthorizePath, m.authorizePOSTHandler)
s.AttachHandler(http.MethodGet, OauthAuthorizePath, m.AuthorizeGETHandler)
s.AttachHandler(http.MethodPost, OauthAuthorizePath, m.AuthorizePOSTHandler)
s.AttachMiddleware(m.oauthTokenMiddleware)
s.AttachMiddleware(m.OauthTokenMiddleware)
return nil
}
func (m *authModule) CreateTables(db db.DB) error {
// CreateTables creates the necessary tables for this module in the given database
func (m *Module) CreateTables(db db.DB) error {
models := []interface{}{
&oauth.Client{},
&oauth.Token{},

View File

@ -31,10 +31,10 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/mastotypes/mastomodel"
)
// authorizeGETHandler should be served as GET at https://example.org/oauth/authorize
// AuthorizeGETHandler should be served as GET at https://example.org/oauth/authorize
// The idea here is to present an oauth authorize page to the user, with a button
// that they have to click to accept. See here: https://docs.joinmastodon.org/methods/apps/oauth/#authorize-a-user
func (m *authModule) authorizeGETHandler(c *gin.Context) {
func (m *Module) AuthorizeGETHandler(c *gin.Context) {
l := m.log.WithField("func", "AuthorizeGETHandler")
s := sessions.Default(c)
@ -46,7 +46,7 @@ func (m *authModule) authorizeGETHandler(c *gin.Context) {
if err := parseAuthForm(c, l); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
} else {
c.Redirect(http.StatusFound, authSignInPath)
c.Redirect(http.StatusFound, AuthSignInPath)
}
return
}
@ -108,11 +108,11 @@ func (m *authModule) authorizeGETHandler(c *gin.Context) {
})
}
// authorizePOSTHandler should be served as POST at https://example.org/oauth/authorize
// AuthorizePOSTHandler should be served as POST at https://example.org/oauth/authorize
// At this point we assume that the user has A) logged in and B) accepted that the app should act for them,
// so we should proceed with the authentication flow and generate an oauth token for them if we can.
// See here: https://docs.joinmastodon.org/methods/apps/oauth/#authorize-a-user
func (m *authModule) authorizePOSTHandler(c *gin.Context) {
func (m *Module) AuthorizePOSTHandler(c *gin.Context) {
l := m.log.WithField("func", "AuthorizePOSTHandler")
s := sessions.Default(c)

View File

@ -24,12 +24,12 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)
// oauthTokenMiddleware checks if the client has presented a valid oauth Bearer token.
// OauthTokenMiddleware checks if the client has presented a valid oauth Bearer token.
// If so, it will check the User that the token belongs to, and set that in the context of
// the request. Then, it will look up the account for that user, and set that in the request too.
// If user or account can't be found, then the handler won't *fail*, in case the server wants to allow
// public requests that don't have a Bearer token set (eg., for public instance information and so on).
func (m *authModule) oauthTokenMiddleware(c *gin.Context) {
func (m *Module) OauthTokenMiddleware(c *gin.Context) {
l := m.log.WithField("func", "ValidatePassword")
l.Trace("entering OauthTokenMiddleware")

View File

@ -28,23 +28,24 @@ import (
"golang.org/x/crypto/bcrypt"
)
// login just wraps a form-submitted username (we want an email) and password
type login struct {
Email string `form:"username"`
Password string `form:"password"`
}
// signInGETHandler should be served at https://example.org/auth/sign_in.
// SignInGETHandler should be served at https://example.org/auth/sign_in.
// The idea is to present a sign in page to the user, where they can enter their username and password.
// The form will then POST to the sign in page, which will be handled by SignInPOSTHandler
func (m *authModule) signInGETHandler(c *gin.Context) {
func (m *Module) SignInGETHandler(c *gin.Context) {
m.log.WithField("func", "SignInGETHandler").Trace("serving sign in html")
c.HTML(http.StatusOK, "sign-in.tmpl", gin.H{})
}
// signInPOSTHandler should be served at https://example.org/auth/sign_in.
// SignInPOSTHandler should be served at https://example.org/auth/sign_in.
// The idea is to present a sign in page to the user, where they can enter their username and password.
// The handler will then redirect to the auth handler served at /auth
func (m *authModule) signInPOSTHandler(c *gin.Context) {
func (m *Module) SignInPOSTHandler(c *gin.Context) {
l := m.log.WithField("func", "SignInPOSTHandler")
s := sessions.Default(c)
form := &login{}
@ -54,7 +55,7 @@ func (m *authModule) signInPOSTHandler(c *gin.Context) {
}
l.Tracef("parsed form: %+v", form)
userid, err := m.validatePassword(form.Email, form.Password)
userid, err := m.ValidatePassword(form.Email, form.Password)
if err != nil {
c.String(http.StatusForbidden, err.Error())
return
@ -67,14 +68,14 @@ func (m *authModule) signInPOSTHandler(c *gin.Context) {
}
l.Trace("redirecting to auth page")
c.Redirect(http.StatusFound, oauthAuthorizePath)
c.Redirect(http.StatusFound, OauthAuthorizePath)
}
// validatePassword takes an email address and a password.
// ValidatePassword takes an email address and a password.
// The goal is to authenticate the password against the one for that email
// address stored in the database. If OK, we return the userid (a uuid) for that user,
// so that it can be used in further Oauth flows to generate a token/retreieve an oauth client from the db.
func (m *authModule) validatePassword(email string, password string) (userid string, err error) {
func (m *Module) ValidatePassword(email string, password string) (userid string, err error) {
l := m.log.WithField("func", "ValidatePassword")
// make sure an email/password was provided and bail if not

View File

@ -24,10 +24,10 @@ import (
"github.com/gin-gonic/gin"
)
// tokenPOSTHandler should be served as a POST at https://example.org/oauth/token
// TokenPOSTHandler should be served as a POST at https://example.org/oauth/token
// The idea here is to serve an oauth access token to a user, which can be used for authorizing against non-public APIs.
// See https://docs.joinmastodon.org/methods/apps/oauth/#obtain-a-token
func (m *authModule) tokenPOSTHandler(c *gin.Context) {
func (m *Module) TokenPOSTHandler(c *gin.Context) {
l := m.log.WithField("func", "TokenPOSTHandler")
l.Trace("entered TokenPOSTHandler")
if err := m.server.HandleTokenRequest(c.Writer, c.Request); err != nil {