whole buncha stuff
This commit is contained in:
parent
b48072fef6
commit
4e281f31b0
2
go.mod
2
go.mod
|
@ -18,7 +18,7 @@ require (
|
||||||
github.com/tidwall/buntdb v1.2.0 // indirect
|
github.com/tidwall/buntdb v1.2.0 // indirect
|
||||||
github.com/tidwall/pretty v1.1.0 // indirect
|
github.com/tidwall/pretty v1.1.0 // indirect
|
||||||
github.com/urfave/cli/v2 v2.3.0
|
github.com/urfave/cli/v2 v2.3.0
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect
|
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
gopkg.in/yaml.v2 v2.3.0
|
gopkg.in/yaml.v2 v2.3.0
|
||||||
)
|
)
|
||||||
|
|
3
go.sum
3
go.sum
|
@ -240,8 +240,9 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
|
|
||||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
|
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b h1:wSOdpTq0/eI46Ez/LkDwIsAKA71YP2SRKBODiRWM0as=
|
||||||
|
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
|
|
@ -35,6 +35,10 @@ type Server interface {
|
||||||
Stop()
|
Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AddsRoutes interface {
|
||||||
|
AddRoutes(s Server) error
|
||||||
|
}
|
||||||
|
|
||||||
type server struct {
|
type server struct {
|
||||||
APIGroup *gin.RouterGroup
|
APIGroup *gin.RouterGroup
|
||||||
logger *logrus.Logger
|
logger *logrus.Logger
|
||||||
|
|
|
@ -25,7 +25,6 @@ import (
|
||||||
|
|
||||||
"github.com/go-fed/activity/pub"
|
"github.com/go-fed/activity/pub"
|
||||||
"github.com/gotosocial/gotosocial/internal/config"
|
"github.com/gotosocial/gotosocial/internal/config"
|
||||||
"github.com/gotosocial/oauth2/v4"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -40,11 +39,6 @@ type DB interface {
|
||||||
*/
|
*/
|
||||||
pub.Database
|
pub.Database
|
||||||
|
|
||||||
/*
|
|
||||||
OAUTH2 DATABASE FUNCTIONS
|
|
||||||
*/
|
|
||||||
TokenStore() oauth2.TokenStore
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ANY ADDITIONAL DESIRED FUNCTIONS
|
ANY ADDITIONAL DESIRED FUNCTIONS
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -315,8 +315,9 @@ func (ps *postgresService) Stop(ctx context.Context) error {
|
||||||
|
|
||||||
func (ps *postgresService) CreateSchema(ctx context.Context) error {
|
func (ps *postgresService) CreateSchema(ctx context.Context) error {
|
||||||
models := []interface{}{
|
models := []interface{}{
|
||||||
(*gtsmodel.GTSAccount)(nil),
|
(*gtsmodel.Account)(nil),
|
||||||
(*gtsmodel.GTSStatus)(nil),
|
(*gtsmodel.Status)(nil),
|
||||||
|
(*gtsmodel.User)(nil),
|
||||||
}
|
}
|
||||||
ps.log.Info("creating db schema")
|
ps.log.Info("creating db schema")
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
GoToSocial
|
||||||
|
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// package email provides a service for interacting with an SMTP server
|
||||||
|
package email
|
|
@ -26,10 +26,10 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GTSAccount represents a GoToSocial user account
|
// Account represents a GoToSocial user account
|
||||||
type GTSAccount struct {
|
type Account struct {
|
||||||
GTSAvatar
|
Avatar
|
||||||
GTSHeader
|
Header
|
||||||
URI string
|
URI string
|
||||||
URL string
|
URL string
|
||||||
ID string `pg:"type:uuid,default:gen_random_uuid(),pk,notnull"`
|
ID string `pg:"type:uuid,default:gen_random_uuid(),pk,notnull"`
|
||||||
|
@ -66,7 +66,7 @@ type GTSAccount struct {
|
||||||
SuspensionOrigin int
|
SuspensionOrigin int
|
||||||
}
|
}
|
||||||
|
|
||||||
type GTSAvatar struct {
|
type Avatar struct {
|
||||||
AvatarFileName string
|
AvatarFileName string
|
||||||
AvatarContentType string
|
AvatarContentType string
|
||||||
AvatarFileSize int
|
AvatarFileSize int
|
||||||
|
@ -75,7 +75,7 @@ type GTSAvatar struct {
|
||||||
AvatarStorageSchemaVersion int
|
AvatarStorageSchemaVersion int
|
||||||
}
|
}
|
||||||
|
|
||||||
type GTSHeader struct {
|
type Header struct {
|
||||||
HeaderFileName string
|
HeaderFileName string
|
||||||
HeaderContentType string
|
HeaderContentType string
|
||||||
HeaderFileSize int
|
HeaderFileSize int
|
||||||
|
|
|
@ -20,7 +20,7 @@ package gtsmodel
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type GTSStatus struct {
|
type Status struct {
|
||||||
ID string `pg:"type:uuid,default:gen_random_uuid(),pk,notnull"`
|
ID string `pg:"type:uuid,default:gen_random_uuid(),pk,notnull"`
|
||||||
URI string
|
URI string
|
||||||
URL string
|
URL string
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
GoToSocial
|
||||||
|
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package gtsmodel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
ID string `pg:"type:uuid,default:gen_random_uuid(),pk,notnull"`
|
||||||
|
Email string `pg:",notnull"`
|
||||||
|
CreatedAt time.Time `pg:"type:timestamp,notnull"`
|
||||||
|
UpdatedAt time.Time `pg:"type:timestamp,notnull"`
|
||||||
|
EncryptedPassword string `pg:",notnull"`
|
||||||
|
ResetPasswordToken string
|
||||||
|
ResetPasswordSentAt time.Time `pg:"type:timestamp"`
|
||||||
|
SignInCount int
|
||||||
|
CurrentSignInAt time.Time `pg:"type:timestamp"`
|
||||||
|
LastSignInAt time.Time `pg:"type:timestamp"`
|
||||||
|
CurrentSignInIP net.IP
|
||||||
|
LastSignInIP net.IP
|
||||||
|
Admin bool
|
||||||
|
ConfirmationToken string
|
||||||
|
ConfirmedAt time.Time `pg:"type:timestamp"`
|
||||||
|
ConfirmationSentAt time.Time `pg:"type:timestamp"`
|
||||||
|
UnconfirmedEmail string
|
||||||
|
Locale string
|
||||||
|
EncryptedOTPSecret string
|
||||||
|
EncryptedOTPSecretIv string
|
||||||
|
EncryptedOTPSecretSalt string
|
||||||
|
ConsumedTimestamp int
|
||||||
|
OTPRequiredForLogin bool
|
||||||
|
LastEmailedAt time.Time `pg:"type:timestamp"`
|
||||||
|
OTPBackupCodes []string
|
||||||
|
FilteredLanguages []string
|
||||||
|
AccountID string `pg:",notnull"`
|
||||||
|
Disabled bool
|
||||||
|
Moderator bool
|
||||||
|
InviteID string
|
||||||
|
RememberToken string
|
||||||
|
ChosenLanguages []string
|
||||||
|
CreatedByApplicationID string
|
||||||
|
Approved bool
|
||||||
|
SignInToken string
|
||||||
|
SignInTokenSentAt time.Time `pg:"type:timestamp"`
|
||||||
|
WebauthnID string
|
||||||
|
SignUpIP net.IP
|
||||||
|
}
|
|
@ -19,19 +19,25 @@
|
||||||
package oauth
|
package oauth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-pg/pg/v10"
|
||||||
|
"github.com/gotosocial/gotosocial/internal/api"
|
||||||
|
"github.com/gotosocial/gotosocial/internal/gtsmodel"
|
||||||
"github.com/gotosocial/oauth2/v4"
|
"github.com/gotosocial/oauth2/v4"
|
||||||
"github.com/gotosocial/oauth2/v4/errors"
|
"github.com/gotosocial/oauth2/v4/errors"
|
||||||
"github.com/gotosocial/oauth2/v4/manage"
|
"github.com/gotosocial/oauth2/v4/manage"
|
||||||
"github.com/gotosocial/oauth2/v4/server"
|
"github.com/gotosocial/oauth2/v4/server"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
manager *manage.Manager
|
manager *manage.Manager
|
||||||
server *server.Server
|
server *server.Server
|
||||||
|
conn *pg.DB
|
||||||
|
log *logrus.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ts oauth2.TokenStore, cs oauth2.ClientStore, log *logrus.Logger) *API {
|
func New(ts oauth2.TokenStore, cs oauth2.ClientStore, conn *pg.DB, log *logrus.Logger) *API {
|
||||||
manager := manage.NewDefaultManager()
|
manager := manage.NewDefaultManager()
|
||||||
manager.MapTokenStorage(ts)
|
manager.MapTokenStorage(ts)
|
||||||
manager.MapClientStorage(cs)
|
manager.MapClientStorage(cs)
|
||||||
|
@ -49,5 +55,41 @@ func New(ts oauth2.TokenStore, cs oauth2.ClientStore, log *logrus.Logger) *API {
|
||||||
return &API{
|
return &API{
|
||||||
manager: manager,
|
manager: manager,
|
||||||
server: srv,
|
server: srv,
|
||||||
|
conn: conn,
|
||||||
|
log: log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *API) AddRoutes(s api.Server) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func incorrectPassword() (string, error) {
|
||||||
|
return "", errors.New("password/email combination was incorrect")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) PasswordAuthorizationHandler(email string, password string) (userid string, err error) {
|
||||||
|
// first we select the user from the database based on email address, bail if no user found for that email
|
||||||
|
gtsUser := >smodel.User{}
|
||||||
|
if err := a.conn.Model(gtsUser).Where("email = ?", email).Select(); err != nil {
|
||||||
|
a.log.Debugf("user %s was not retrievable from db during oauth authorization attempt: %s", email, err)
|
||||||
|
return incorrectPassword()
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure a password is actually set and bail if not
|
||||||
|
if gtsUser.EncryptedPassword == "" {
|
||||||
|
a.log.Warnf("encrypted password for user %s was empty for some reason", gtsUser.Email)
|
||||||
|
return incorrectPassword()
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare the provided password with the encrypted one from the db, bail if they don't match
|
||||||
|
if err := bcrypt.CompareHashAndPassword([]byte(gtsUser.EncryptedPassword), []byte(password)); err != nil {
|
||||||
|
a.log.Debugf("password hash didn't match for user %s during login attempt: %s", gtsUser.Email, err)
|
||||||
|
return incorrectPassword()
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've made it this far the email/password is correct so we need the oauth client-id of the user
|
||||||
|
// This is, conveniently, the same as the user ID, so we can just return it.
|
||||||
|
userid = gtsUser.ID
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -37,9 +37,9 @@ func NewPGClientStore(conn *pg.DB) oauth2.ClientStore {
|
||||||
return pts
|
return pts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pcs *pgClientStore) GetByID(ctx context.Context, id string) (oauth2.ClientInfo, error) {
|
func (pcs *pgClientStore) GetByID(ctx context.Context, clientID string) (oauth2.ClientInfo, error) {
|
||||||
poc := &oauthClient{
|
poc := &oauthClient{
|
||||||
ID: id,
|
ID: clientID,
|
||||||
}
|
}
|
||||||
if err := pcs.conn.WithContext(ctx).Model(poc).Where("id = ?", poc.ID).Select(); err != nil {
|
if err := pcs.conn.WithContext(ctx).Model(poc).Where("id = ?", poc.ID).Select(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
Loading…
Reference in New Issue