feat: add skeleton of discord-auth, resolve gazelle issues.. again

This commit is contained in:
41666 2020-09-23 23:44:57 -04:00
parent deb6c194e9
commit fce28b5b37
19 changed files with 257 additions and 23 deletions

View file

@ -499,6 +499,12 @@ def go_repositories():
sum = "h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=",
version = "v2.0.1",
)
go_repository(
name = "com_github_segmentio_ksuid",
importpath = "github.com/segmentio/ksuid",
sum = "h1:FoResxvleQwYiPAVKe1tMUlEirodZqlqglIuFsdDntY=",
version = "v1.0.3",
)
go_repository(
name = "com_github_shurcool_sanitized_anchor_name",
importpath = "github.com/shurcooL/sanitized_anchor_name",

2
go.mod
View file

@ -6,8 +6,10 @@ require (
github.com/bwmarrin/discordgo v0.22.0
github.com/facebook/ent v0.4.3
github.com/joho/godotenv v1.3.0
github.com/julienschmidt/httprouter v1.2.0
github.com/lampjaw/discordclient v0.0.0-20200923011548-6558fc9e89df
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/segmentio/ksuid v1.0.3
go.uber.org/fx v1.13.1
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a // indirect

View file

@ -36,10 +36,10 @@ go_library(
"//src/db/ent/predicate",
"//src/db/ent/schema",
"//src/db/ent/session",
"@com_github_facebook_ent//:go_default_library",
"@com_github_facebook_ent//dialect:go_default_library",
"@com_github_facebook_ent//dialect/sql:go_default_library",
"@com_github_facebook_ent//dialect/sql/sqlgraph:go_default_library",
"@com_github_facebook_ent//schema/field:go_default_library",
"@com_github_facebook_ent//:ent",
"@com_github_facebook_ent//dialect",
"@com_github_facebook_ent//dialect/sql",
"@com_github_facebook_ent//dialect/sql/sqlgraph",
"@com_github_facebook_ent//schema/field",
],
)

View file

@ -10,6 +10,6 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//src/db/ent/predicate",
"@com_github_facebook_ent//dialect/sql:go_default_library",
"@com_github_facebook_ent//dialect/sql",
],
)

View file

@ -8,6 +8,6 @@ go_library(
deps = [
"//src/db/ent",
"//src/db/ent/runtime",
"@com_github_facebook_ent//dialect/sql/schema:go_default_library",
"@com_github_facebook_ent//dialect/sql/schema",
],
)

View file

@ -10,6 +10,6 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//src/db/ent/predicate",
"@com_github_facebook_ent//dialect/sql:go_default_library",
"@com_github_facebook_ent//dialect/sql",
],
)

View file

@ -9,8 +9,8 @@ go_library(
importpath = "github.com/roleypoly/roleypoly/src/db/ent/migrate",
visibility = ["//visibility:public"],
deps = [
"@com_github_facebook_ent//dialect:go_default_library",
"@com_github_facebook_ent//dialect/sql/schema:go_default_library",
"@com_github_facebook_ent//schema/field:go_default_library",
"@com_github_facebook_ent//dialect",
"@com_github_facebook_ent//dialect/sql/schema",
"@com_github_facebook_ent//schema/field",
],
)

View file

@ -5,5 +5,5 @@ go_library(
srcs = ["predicate.go"],
importpath = "github.com/roleypoly/roleypoly/src/db/ent/predicate",
visibility = ["//visibility:public"],
deps = ["@com_github_facebook_ent//dialect/sql:go_default_library"],
deps = ["@com_github_facebook_ent//dialect/sql"],
)

View file

@ -10,8 +10,8 @@ go_library(
importpath = "github.com/roleypoly/roleypoly/src/db/ent/schema",
visibility = ["//visibility:public"],
deps = [
"@com_github_facebook_ent//:go_default_library",
"@com_github_facebook_ent//schema/field:go_default_library",
"@com_github_facebook_ent//schema/mixin:go_default_library",
"@com_github_facebook_ent//:ent",
"@com_github_facebook_ent//schema/field",
"@com_github_facebook_ent//schema/mixin",
],
)

View file

@ -10,6 +10,6 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//src/db/ent/predicate",
"@com_github_facebook_ent//dialect/sql:go_default_library",
"@com_github_facebook_ent//dialect/sql",
],
)

View file

@ -7,7 +7,13 @@ go_library(
srcs = ["discord-auth.go"],
importpath = "github.com/roleypoly/roleypoly/src/discord-auth",
visibility = ["//visibility:private"],
deps = ["@org_uber_go_fx//:go_default_library"],
deps = [
"//src/common/version",
"//src/discord-auth/http",
"@com_github_julienschmidt_httprouter//:httprouter",
"@io_k8s_klog//:klog",
"@org_uber_go_fx//:fx",
],
)
go_binary(

View file

@ -0,0 +1,21 @@
# Discord Auth
Service for handling Discord OAuth flow.
## Responsibilities
- Redirect users to relevant Discord OAuth page w/ state
- Handle redirect from Discord OAuth flow and process the token
- Modify active session to include relevant data
- v3: for parity, this is just user data
- _vNext: get guilds from oauth and cache_
- _vNext: Source of truth for user guilds_
## Boundaries & Services
- **Inbound**
- HTTP: /discord-auth/\*
- gRPC: DiscordAuthService
- **Outbound**
- Redis
- gRPC: SessionService

View file

@ -1,11 +1,54 @@
package main
import "go.uber.org/fx"
import (
"context"
"net/http"
"github.com/julienschmidt/httprouter"
"go.uber.org/fx"
"k8s.io/klog"
"github.com/roleypoly/roleypoly/src/common/version"
httpservice "github.com/roleypoly/roleypoly/src/discord-auth/http"
)
func main() {
klog.Info(version.StartupInfo("discord-auth"))
app := fx.New(
// fx.Invoke(StartDiscordAuthService),
fx.Provide(
httprouter.New,
httpservice.NewHTTPService,
),
fx.Invoke(
httpservice.RegisterRoutes,
newHTTPServer,
),
)
app.Run()
}
func newHTTPServer(lc fx.Lifecycle, router *httprouter.Router) *http.Server {
server := &http.Server{
Addr: ":8080",
Handler: router,
}
lc.Append(fx.Hook{
OnStart: func(context.Context) error {
klog.Info("Starting HTTP Server")
go server.ListenAndServe()
return nil
},
OnStop: func(ctx context.Context) error {
klog.Info("Stopping HTTP Server")
return server.Shutdown(ctx)
},
})
return server
}
func startupHTTP()

View file

@ -0,0 +1,25 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "http",
srcs = [
"httpservice.go",
"oauth.go",
],
importpath = "github.com/roleypoly/roleypoly/src/discord-auth/http",
visibility = ["//visibility:public"],
deps = [
"@com_github_julienschmidt_httprouter//:httprouter",
"@com_github_segmentio_ksuid//:ksuid",
],
)
go_test(
name = "http_test",
srcs = [
"httpservice_test.go",
"oauth_test.go",
],
embed = [":http"],
deps = ["@com_github_julienschmidt_httprouter//:httprouter"],
)

View file

@ -0,0 +1,34 @@
package httpservice
import "github.com/julienschmidt/httprouter"
type HTTPService struct {
config struct {
ClientID string
PublicURL string
}
}
func NewHTTPService() *HTTPService {
return &HTTPService{}
}
func RegisterRoutes(s *HTTPService, router *httprouter.Router) {
s.RegisterRoutes(router)
}
func (h *HTTPService) RegisterRoutes(router *httprouter.Router) {
router.GET(h.v3("/oauth-handoff"), h.oauthHandoffv3)
}
func (*HTTPService) v3(path string) string {
return `/discord-auth/v3` + path
}
func (*HTTPService) v4(path string) string {
return `/discord-auth/v4` + path
}
func (h *HTTPService) getOauthRedirectURL() string {
return h.config.PublicURL + h.v3("/oauth-callback")
}

View file

@ -0,0 +1,43 @@
package httpservice
import (
"testing"
"github.com/julienschmidt/httprouter"
)
func TestV3Route(t *testing.T) {
s := &HTTPService{}
url := s.v3("/test")
if url != "/discord-auth/v3/test" {
t.FailNow()
}
}
func TestV4Route(t *testing.T) {
s := &HTTPService{}
url := s.v4("/test")
if url != "/discord-auth/v4/test" {
t.FailNow()
}
}
func TestRegisterRoutes(t *testing.T) {
s := NewHTTPService()
r := httprouter.New()
RegisterRoutes(s, r)
}
func TestOauthRedirectURL(t *testing.T) {
s := &HTTPService{
config: struct{ ClientID, PublicURL string }{
ClientID: "",
PublicURL: "https://roleypoly.local",
},
}
url := s.getOauthRedirectURL()
if url != "https://roleypoly.local/discord-auth/v3/oauth-callback" {
t.FailNow()
}
}

View file

@ -0,0 +1,25 @@
package httpservice
import (
"fmt"
"net/http"
"github.com/julienschmidt/httprouter"
"github.com/segmentio/ksuid"
)
// Handles flow start request by redirecting the user to Discord OAuth page
func (h *HTTPService) oauthHandoffv3(rw http.ResponseWriter, r *http.Request, _ httprouter.Params) {
// TODO: actually create and store this state
requestState := ksuid.New().String()
redirectURL := fmt.Sprintf(
`https://discord.com/oauth2/authorize?client_id=%s&redirect_uri=%s&response_type=code&scope=identify&state=%s`,
h.config.ClientID,
h.getOauthRedirectURL(),
requestState,
)
rw.Header().Add("location", redirectURL)
rw.WriteHeader(303)
}

View file

@ -0,0 +1,29 @@
package httpservice
import (
"net/http/httptest"
"strings"
"testing"
"github.com/julienschmidt/httprouter"
)
func TestOauthHandoffV3(t *testing.T) {
s := NewHTTPService()
s.config.ClientID = "test1234"
s.config.PublicURL = "https://roleypoly.test"
rw := httptest.NewRecorder()
r := httptest.NewRequest("GET", s.v3("/oauth-handoff"), nil)
ps := httprouter.Params{}
s.oauthHandoffv3(rw, r, ps)
if rw.Result().StatusCode != 303 {
t.Error("Status code was not 303, got ", rw.Result().StatusCode)
}
if !strings.Contains(rw.Result().Header.Get("location"), s.config.ClientID) &&
!strings.Contains(rw.Result().Header.Get("location"), s.getOauthRedirectURL()) {
t.Error("Location was not correct, got ", rw.Result().Header.Get("location"))
}
}

View file

@ -13,10 +13,10 @@ go_library(
deps = [
"//src/common/version",
"//src/discord-bot/internal/strings",
"@com_github_bwmarrin_discordgo//:go_default_library",
"@com_github_joho_godotenv//autoload:go_default_library",
"@com_github_lampjaw_discordclient//:go_default_library",
"@io_k8s_klog//:go_default_library",
"@com_github_bwmarrin_discordgo//:discordgo",
"@com_github_joho_godotenv//autoload",
"@com_github_lampjaw_discordclient//:discordclient",
"@io_k8s_klog//:klog",
],
)