Add first login route
This commit is contained in:
@@ -5,8 +5,8 @@ package ent
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"ersteller-lib/starter/ent/googleauth"
|
"ersteller-lib/starter/ent/googleauth"
|
||||||
|
"ersteller-lib/starter/ent/schema"
|
||||||
"ersteller-lib/starter/ent/user"
|
"ersteller-lib/starter/ent/user"
|
||||||
"ersteller-lib/starter/google"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -25,7 +25,7 @@ type GoogleAuth struct {
|
|||||||
// UpdatedAt holds the value of the "updated_at" field.
|
// UpdatedAt holds the value of the "updated_at" field.
|
||||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||||
// Credentials holds the value of the "credentials" field.
|
// Credentials holds the value of the "credentials" field.
|
||||||
Credentials google.Credentials `json:"credentials,omitempty"`
|
Credentials schema.Credentials `json:"credentials,omitempty"`
|
||||||
// Edges holds the relations/edges for other nodes in the graph.
|
// Edges holds the relations/edges for other nodes in the graph.
|
||||||
// The values are being populated by the GoogleAuthQuery when eager-loading is set.
|
// The values are being populated by the GoogleAuthQuery when eager-loading is set.
|
||||||
Edges GoogleAuthEdges `json:"edges"`
|
Edges GoogleAuthEdges `json:"edges"`
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"ersteller-lib/starter/ent/googleauth"
|
"ersteller-lib/starter/ent/googleauth"
|
||||||
|
"ersteller-lib/starter/ent/schema"
|
||||||
"ersteller-lib/starter/ent/user"
|
"ersteller-lib/starter/ent/user"
|
||||||
"ersteller-lib/starter/google"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ func (_c *GoogleAuthCreate) SetNillableUpdatedAt(v *time.Time) *GoogleAuthCreate
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetCredentials sets the "credentials" field.
|
// SetCredentials sets the "credentials" field.
|
||||||
func (_c *GoogleAuthCreate) SetCredentials(v google.Credentials) *GoogleAuthCreate {
|
func (_c *GoogleAuthCreate) SetCredentials(v schema.Credentials) *GoogleAuthCreate {
|
||||||
_c.mutation.SetCredentials(v)
|
_c.mutation.SetCredentials(v)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"ersteller-lib/starter/ent/googleauth"
|
"ersteller-lib/starter/ent/googleauth"
|
||||||
"ersteller-lib/starter/ent/predicate"
|
"ersteller-lib/starter/ent/predicate"
|
||||||
|
"ersteller-lib/starter/ent/schema"
|
||||||
"ersteller-lib/starter/ent/user"
|
"ersteller-lib/starter/ent/user"
|
||||||
"ersteller-lib/starter/google"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -37,13 +37,13 @@ func (_u *GoogleAuthUpdate) SetUpdatedAt(v time.Time) *GoogleAuthUpdate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetCredentials sets the "credentials" field.
|
// SetCredentials sets the "credentials" field.
|
||||||
func (_u *GoogleAuthUpdate) SetCredentials(v google.Credentials) *GoogleAuthUpdate {
|
func (_u *GoogleAuthUpdate) SetCredentials(v schema.Credentials) *GoogleAuthUpdate {
|
||||||
_u.mutation.SetCredentials(v)
|
_u.mutation.SetCredentials(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableCredentials sets the "credentials" field if the given value is not nil.
|
// SetNillableCredentials sets the "credentials" field if the given value is not nil.
|
||||||
func (_u *GoogleAuthUpdate) SetNillableCredentials(v *google.Credentials) *GoogleAuthUpdate {
|
func (_u *GoogleAuthUpdate) SetNillableCredentials(v *schema.Credentials) *GoogleAuthUpdate {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_u.SetCredentials(*v)
|
_u.SetCredentials(*v)
|
||||||
}
|
}
|
||||||
@@ -190,13 +190,13 @@ func (_u *GoogleAuthUpdateOne) SetUpdatedAt(v time.Time) *GoogleAuthUpdateOne {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetCredentials sets the "credentials" field.
|
// SetCredentials sets the "credentials" field.
|
||||||
func (_u *GoogleAuthUpdateOne) SetCredentials(v google.Credentials) *GoogleAuthUpdateOne {
|
func (_u *GoogleAuthUpdateOne) SetCredentials(v schema.Credentials) *GoogleAuthUpdateOne {
|
||||||
_u.mutation.SetCredentials(v)
|
_u.mutation.SetCredentials(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableCredentials sets the "credentials" field if the given value is not nil.
|
// SetNillableCredentials sets the "credentials" field if the given value is not nil.
|
||||||
func (_u *GoogleAuthUpdateOne) SetNillableCredentials(v *google.Credentials) *GoogleAuthUpdateOne {
|
func (_u *GoogleAuthUpdateOne) SetNillableCredentials(v *schema.Credentials) *GoogleAuthUpdateOne {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_u.SetCredentials(*v)
|
_u.SetCredentials(*v)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"ersteller-lib/starter/ent/googleauth"
|
"ersteller-lib/starter/ent/googleauth"
|
||||||
"ersteller-lib/starter/ent/predicate"
|
"ersteller-lib/starter/ent/predicate"
|
||||||
|
"ersteller-lib/starter/ent/schema"
|
||||||
"ersteller-lib/starter/ent/user"
|
"ersteller-lib/starter/ent/user"
|
||||||
"ersteller-lib/starter/google"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -38,7 +38,7 @@ type GoogleAuthMutation struct {
|
|||||||
id *int
|
id *int
|
||||||
created_at *time.Time
|
created_at *time.Time
|
||||||
updated_at *time.Time
|
updated_at *time.Time
|
||||||
credentials *google.Credentials
|
credentials *schema.Credentials
|
||||||
clearedFields map[string]struct{}
|
clearedFields map[string]struct{}
|
||||||
user *int
|
user *int
|
||||||
cleareduser bool
|
cleareduser bool
|
||||||
@@ -218,12 +218,12 @@ func (m *GoogleAuthMutation) ResetUpdatedAt() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetCredentials sets the "credentials" field.
|
// SetCredentials sets the "credentials" field.
|
||||||
func (m *GoogleAuthMutation) SetCredentials(_go google.Credentials) {
|
func (m *GoogleAuthMutation) SetCredentials(s schema.Credentials) {
|
||||||
m.credentials = &_go
|
m.credentials = &s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Credentials returns the value of the "credentials" field in the mutation.
|
// Credentials returns the value of the "credentials" field in the mutation.
|
||||||
func (m *GoogleAuthMutation) Credentials() (r google.Credentials, exists bool) {
|
func (m *GoogleAuthMutation) Credentials() (r schema.Credentials, exists bool) {
|
||||||
v := m.credentials
|
v := m.credentials
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return
|
return
|
||||||
@@ -234,7 +234,7 @@ func (m *GoogleAuthMutation) Credentials() (r google.Credentials, exists bool) {
|
|||||||
// OldCredentials returns the old "credentials" field's value of the GoogleAuth entity.
|
// OldCredentials returns the old "credentials" field's value of the GoogleAuth entity.
|
||||||
// If the GoogleAuth object wasn't provided to the builder, the object is fetched from the database.
|
// If the GoogleAuth object wasn't provided to the builder, the object is fetched from the database.
|
||||||
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
|
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
|
||||||
func (m *GoogleAuthMutation) OldCredentials(ctx context.Context) (v google.Credentials, err error) {
|
func (m *GoogleAuthMutation) OldCredentials(ctx context.Context) (v schema.Credentials, err error) {
|
||||||
if !m.op.Is(OpUpdateOne) {
|
if !m.op.Is(OpUpdateOne) {
|
||||||
return v, errors.New("OldCredentials is only allowed on UpdateOne operations")
|
return v, errors.New("OldCredentials is only allowed on UpdateOne operations")
|
||||||
}
|
}
|
||||||
@@ -389,7 +389,7 @@ func (m *GoogleAuthMutation) SetField(name string, value ent.Value) error {
|
|||||||
m.SetUpdatedAt(v)
|
m.SetUpdatedAt(v)
|
||||||
return nil
|
return nil
|
||||||
case googleauth.FieldCredentials:
|
case googleauth.FieldCredentials:
|
||||||
v, ok := value.(google.Credentials)
|
v, ok := value.(schema.Credentials)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("unexpected type %T for field %s", value, name)
|
return fmt.Errorf("unexpected type %T for field %s", value, name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package google
|
package schema
|
||||||
|
|
||||||
import "golang.org/x/oauth2"
|
import "golang.org/x/oauth2"
|
||||||
|
|
||||||
@@ -2,7 +2,6 @@ package schema
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
ersteller_ent "ersteller-lib/schema/ent"
|
ersteller_ent "ersteller-lib/schema/ent"
|
||||||
google "ersteller-lib/starter/google"
|
|
||||||
|
|
||||||
"entgo.io/ent"
|
"entgo.io/ent"
|
||||||
"entgo.io/ent/schema/edge"
|
"entgo.io/ent/schema/edge"
|
||||||
@@ -21,7 +20,7 @@ func (GoogleAuth) Mixin() []ent.Mixin {
|
|||||||
|
|
||||||
func (GoogleAuth) Fields() []ent.Field {
|
func (GoogleAuth) Fields() []ent.Field {
|
||||||
return []ent.Field{
|
return []ent.Field{
|
||||||
field.JSON("credentials", google.Credentials{}),
|
field.JSON("credentials", Credentials{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+2
@@ -133,6 +133,8 @@ func GenerateEnvFile(rootPath string, overwrite bool) error {
|
|||||||
|
|
||||||
// Define default values and comments for specific keys
|
// Define default values and comments for specific keys
|
||||||
defaults := map[string]string{
|
defaults := map[string]string{
|
||||||
|
EnvKeyDatabaseURL: "\"db/starter.db?_fk=1\"",
|
||||||
|
EnvKeyBaseURL: "\"http://localhost:8090\"",
|
||||||
EnvKeyIsLocal: "true",
|
EnvKeyIsLocal: "true",
|
||||||
EnvKeyIsDev: "true",
|
EnvKeyIsDev: "true",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
|
. "ersteller-lib"
|
||||||
|
"ersteller-lib/starter/ent"
|
||||||
|
"ersteller-lib/starter/env"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
"golang.org/x/oauth2/google"
|
||||||
|
)
|
||||||
|
|
||||||
|
const oAuthStateCookieName = "oauthstate"
|
||||||
|
const GoogleLogin = "/login/google"
|
||||||
|
const GoogleLoginCallback = "/google/authenticated"
|
||||||
|
|
||||||
|
type GoogleAuth struct {
|
||||||
|
db *ent.Client
|
||||||
|
server *http.ServeMux
|
||||||
|
environment env.Environment
|
||||||
|
config oauth2.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGoogleAuth(db *ent.Client, server *http.ServeMux, environment env.Environment) *GoogleAuth {
|
||||||
|
config := oauth2.Config{
|
||||||
|
ClientID: environment.GoogleClientId,
|
||||||
|
ClientSecret: environment.GoogleClientSecret,
|
||||||
|
Endpoint: google.Endpoint,
|
||||||
|
RedirectURL: environment.BaseUrl + GoogleLoginCallback,
|
||||||
|
Scopes: []string{},
|
||||||
|
}
|
||||||
|
return &GoogleAuth{db: db, server: server, environment: environment, config: config}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GoogleAuth) AddRoutes() {
|
||||||
|
g.server.HandleFunc("GET "+GoogleLogin, func(writer http.ResponseWriter, request *http.Request) {
|
||||||
|
state := g.generateStateOauthCookie(writer)
|
||||||
|
url := g.config.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.ApprovalForce)
|
||||||
|
http.Redirect(writer, request, url, http.StatusTemporaryRedirect)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GoogleAuth) generateStateOauthCookie(w http.ResponseWriter) string {
|
||||||
|
b := make([]byte, 16)
|
||||||
|
_, err := rand.Read(b)
|
||||||
|
if err != nil {
|
||||||
|
LogError("Failed to read random state: %v", err)
|
||||||
|
}
|
||||||
|
state := base64.URLEncoding.EncodeToString(b)
|
||||||
|
|
||||||
|
var expiration = time.Now().Add(time.Hour)
|
||||||
|
cookie := http.Cookie{Name: oAuthStateCookieName, Value: state, Expires: expiration, HttpOnly: true, Path: "/", Secure: false}
|
||||||
|
if g.environment.IsLocal {
|
||||||
|
cookie.SameSite = http.SameSiteLaxMode
|
||||||
|
cookie.Secure = false
|
||||||
|
}
|
||||||
|
http.SetCookie(w, &cookie)
|
||||||
|
|
||||||
|
return state
|
||||||
|
}
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
. "ersteller-lib"
|
. "ersteller-lib"
|
||||||
|
"ersteller-lib/starter/ent"
|
||||||
"ersteller-lib/starter/env"
|
"ersteller-lib/starter/env"
|
||||||
"ersteller-lib/starter/routes"
|
"ersteller-lib/starter/routes"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -13,6 +16,22 @@ func main() {
|
|||||||
|
|
||||||
environment := env.LoadEnvironment()
|
environment := env.LoadEnvironment()
|
||||||
Debug(environment)
|
Debug(environment)
|
||||||
|
|
||||||
|
client, err := ent.Open("sqlite3", environment.DatabaseUrl,
|
||||||
|
ent.Log(log.Println), ent.Debug())
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed opening connection to sqlite: %v", err)
|
||||||
|
}
|
||||||
|
log.Println("client", client)
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
if err := client.Schema.Create(ctx); err != nil {
|
||||||
|
log.Fatalf("failed creating schema resources: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
Debug("starting white label app on port 8090")
|
Debug("starting white label app on port 8090")
|
||||||
handler := routes.CreateApi()
|
handler := routes.CreateApi()
|
||||||
log.Fatal(http.ListenAndServe(":8090", handler))
|
log.Fatal(http.ListenAndServe(":8090", handler))
|
||||||
|
|||||||
Reference in New Issue
Block a user