2023-03-16 03:43:25 -07:00
|
|
|
package db
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"emperror.dev/errors"
|
2023-04-03 19:11:03 -07:00
|
|
|
"github.com/georgysavva/scany/v2/pgxscan"
|
|
|
|
"github.com/jackc/pgx/v5"
|
2023-03-16 03:43:25 -07:00
|
|
|
"golang.org/x/oauth2"
|
|
|
|
)
|
|
|
|
|
|
|
|
type FediverseApp struct {
|
|
|
|
ID int64
|
|
|
|
// Instance is the instance's base API url, excluding schema
|
|
|
|
Instance string
|
|
|
|
ClientID string
|
|
|
|
ClientSecret string
|
|
|
|
InstanceType string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f FediverseApp) ClientConfig() *oauth2.Config {
|
2023-03-24 19:27:40 -07:00
|
|
|
if f.MastodonCompatible() {
|
|
|
|
return &oauth2.Config{
|
|
|
|
ClientID: f.ClientID,
|
|
|
|
ClientSecret: f.ClientSecret,
|
|
|
|
Endpoint: oauth2.Endpoint{
|
|
|
|
AuthURL: "https://" + f.Instance + "/oauth/authorize",
|
|
|
|
TokenURL: "https://" + f.Instance + "/oauth/token",
|
|
|
|
AuthStyle: oauth2.AuthStyleInParams,
|
|
|
|
},
|
|
|
|
Scopes: []string{"read:accounts"},
|
|
|
|
RedirectURL: os.Getenv("BASE_URL") + "/auth/login/mastodon/" + f.Instance,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-16 03:43:25 -07:00
|
|
|
return &oauth2.Config{
|
|
|
|
ClientID: f.ClientID,
|
|
|
|
ClientSecret: f.ClientSecret,
|
|
|
|
Endpoint: oauth2.Endpoint{
|
2023-03-24 19:27:40 -07:00
|
|
|
AuthURL: "https://" + f.Instance + "/auth",
|
|
|
|
TokenURL: "https://" + f.Instance + "/api/auth/session/oauth",
|
|
|
|
AuthStyle: oauth2.AuthStyleInHeader,
|
2023-03-16 03:43:25 -07:00
|
|
|
},
|
2023-03-24 19:27:40 -07:00
|
|
|
Scopes: []string{"read:account"},
|
|
|
|
RedirectURL: os.Getenv("BASE_URL") + "/auth/login/misskey/" + f.Instance,
|
2023-03-16 03:43:25 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f FediverseApp) MastodonCompatible() bool {
|
|
|
|
return f.InstanceType == "mastodon" || f.InstanceType == "pleroma" || f.InstanceType == "akkoma" || f.InstanceType == "pixelfed"
|
|
|
|
}
|
|
|
|
|
2023-03-25 07:54:09 -07:00
|
|
|
func (f FediverseApp) Misskey() bool {
|
|
|
|
return f.InstanceType == "misskey" || f.InstanceType == "foundkey" || f.InstanceType == "calckey"
|
|
|
|
}
|
|
|
|
|
2023-03-16 03:43:25 -07:00
|
|
|
const ErrNoInstanceApp = errors.Sentinel("instance doesn't have an app")
|
|
|
|
|
|
|
|
func (db *DB) FediverseApp(ctx context.Context, instance string) (fa FediverseApp, err error) {
|
|
|
|
sql, args, err := sq.Select("*").From("fediverse_apps").Where("instance = ?", instance).ToSql()
|
|
|
|
if err != nil {
|
|
|
|
return fa, errors.Wrap(err, "building sql")
|
|
|
|
}
|
|
|
|
|
|
|
|
err = pgxscan.Get(ctx, db, &fa, sql, args...)
|
|
|
|
if err != nil {
|
|
|
|
if errors.Cause(err) == pgx.ErrNoRows {
|
|
|
|
return fa, ErrNoInstanceApp
|
|
|
|
}
|
|
|
|
return fa, errors.Wrap(err, "executing query")
|
|
|
|
}
|
|
|
|
return fa, nil
|
|
|
|
}
|
|
|
|
|
2023-03-17 06:14:31 -07:00
|
|
|
func (db *DB) FediverseAppByID(ctx context.Context, id int64) (fa FediverseApp, err error) {
|
|
|
|
sql, args, err := sq.Select("*").From("fediverse_apps").Where("id = ?", id).ToSql()
|
|
|
|
if err != nil {
|
|
|
|
return fa, errors.Wrap(err, "building sql")
|
|
|
|
}
|
|
|
|
|
|
|
|
err = pgxscan.Get(ctx, db, &fa, sql, args...)
|
|
|
|
if err != nil {
|
|
|
|
return fa, errors.Wrap(err, "executing query")
|
|
|
|
}
|
|
|
|
return fa, nil
|
|
|
|
}
|
|
|
|
|
2023-03-16 03:43:25 -07:00
|
|
|
func (db *DB) CreateFediverseApp(ctx context.Context, instance, instanceType, clientID, clientSecret string) (fa FediverseApp, err error) {
|
|
|
|
sql, args, err := sq.Insert("fediverse_apps").
|
|
|
|
Columns("instance", "instance_type", "client_id", "client_secret").
|
|
|
|
Values(instance, instanceType, clientID, clientSecret).
|
|
|
|
Suffix("RETURNING *").ToSql()
|
|
|
|
if err != nil {
|
|
|
|
return fa, errors.Wrap(err, "building query")
|
|
|
|
}
|
|
|
|
|
|
|
|
err = pgxscan.Get(ctx, db, &fa, sql, args...)
|
|
|
|
if err != nil {
|
|
|
|
return fa, errors.Wrap(err, "executing query")
|
|
|
|
}
|
|
|
|
return fa, nil
|
|
|
|
}
|