1
0
mirror of https://github.com/raseels-repos/golang-saas-starter-kit.git synced 2025-06-27 00:51:13 +02:00

Use interface in the handlers of web-api/web-app

This commit is contained in:
huyng
2019-08-17 11:03:48 +07:00
committed by seta-davenguyen
parent 102ca82125
commit d277b0ec25
26 changed files with 294 additions and 163 deletions

View File

@ -4,23 +4,45 @@ import (
"context" "context"
"net/http" "net/http"
"strconv" "strconv"
"time"
"geeks-accelerator/oss/saas-starter-kit/internal/account" "geeks-accelerator/oss/saas-starter-kit/internal/account"
accountref "geeks-accelerator/oss/saas-starter-kit/internal/account/account_preference"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"github.com/pkg/errors" "github.com/pkg/errors"
"gopkg.in/go-playground/validator.v9" "gopkg.in/go-playground/validator.v9"
) )
// Account represents the Account API method handler set. // Account represents the Account API method handler set.
type Account struct { type Accounts struct {
*account.Repository Repository AccountRepository
// ADD OTHER STATE LIKE THE LOGGER AND CONFIG HERE. // ADD OTHER STATE LIKE THE LOGGER AND CONFIG HERE.
} }
type AccountRepository interface {
//CanReadAccount(ctx context.Context, claims auth.Claims, dbConn *sqlx.DB, accountID string) error
Find(ctx context.Context, claims auth.Claims, req account.AccountFindRequest) (account.Accounts, error)
Create(ctx context.Context, claims auth.Claims, req account.AccountCreateRequest, now time.Time) (*account.Account, error)
ReadByID(ctx context.Context, claims auth.Claims, id string) (*account.Account, error)
Read(ctx context.Context, claims auth.Claims, req account.AccountReadRequest) (*account.Account, error)
Update(ctx context.Context, claims auth.Claims, req account.AccountUpdateRequest, now time.Time) error
Archive(ctx context.Context, claims auth.Claims, req account.AccountArchiveRequest, now time.Time) error
Delete(ctx context.Context, claims auth.Claims, req account.AccountDeleteRequest) error
}
type AccountPrefRepository interface {
Find(ctx context.Context, claims auth.Claims, req accountref.AccountPreferenceFindRequest) ([]*accountref.AccountPreference, error)
FindByAccountID(ctx context.Context, claims auth.Claims, req accountref.AccountPreferenceFindByAccountIDRequest) ([]*accountref.AccountPreference, error)
Read(ctx context.Context, claims auth.Claims, req accountref.AccountPreferenceReadRequest) (*accountref.AccountPreference, error)
Set(ctx context.Context, claims auth.Claims, req accountref.AccountPreferenceSetRequest, now time.Time) error
Archive(ctx context.Context, claims auth.Claims, req accountref.AccountPreferenceArchiveRequest, now time.Time) error
Delete(ctx context.Context, claims auth.Claims, req accountref.AccountPreferenceDeleteRequest) error
}
// Read godoc // Read godoc
// @Summary Get account by ID // @Summary Get account by ID
// @Description Read returns the specified account from the system. // @Description Read returns the specified account from the system.
@ -34,7 +56,7 @@ type Account struct {
// @Failure 404 {object} weberror.ErrorResponse // @Failure 404 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /accounts/{id} [get] // @Router /accounts/{id} [get]
func (h *Account) Read(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Accounts) Read(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
claims, ok := ctx.Value(auth.Key).(auth.Claims) claims, ok := ctx.Value(auth.Key).(auth.Claims)
if !ok { if !ok {
return errors.New("claims missing from context") return errors.New("claims missing from context")
@ -81,7 +103,7 @@ func (h *Account) Read(ctx context.Context, w http.ResponseWriter, r *http.Reque
// @Failure 403 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /accounts [patch] // @Router /accounts [patch]
func (h *Account) Update(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Accounts) Update(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
v, err := webcontext.ContextValues(ctx) v, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {

View File

@ -7,13 +7,14 @@ import (
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"geeks-accelerator/oss/saas-starter-kit/internal/project" "geeks-accelerator/oss/saas-starter-kit/internal/project"
"github.com/pkg/errors"
"net/http" "net/http"
"github.com/pkg/errors"
) )
// Example represents the Example API method handler set. // Example represents the Example API method handler set.
type Example struct { type Example struct {
Project *project.Repository Project ProjectRepository
// ADD OTHER STATE LIKE THE LOGGER AND CONFIG HERE. // ADD OTHER STATE LIKE THE LOGGER AND CONFIG HERE.
} }

View File

@ -5,23 +5,35 @@ import (
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
"time"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"geeks-accelerator/oss/saas-starter-kit/internal/project" "geeks-accelerator/oss/saas-starter-kit/internal/project"
"github.com/pkg/errors" "github.com/pkg/errors"
"gopkg.in/go-playground/validator.v9" "gopkg.in/go-playground/validator.v9"
) )
// Project represents the Project API method handler set. // Project represents the Project API method handler set.
type Project struct { type Projects struct {
*project.Repository Repository ProjectRepository
// ADD OTHER STATE LIKE THE LOGGER IF NEEDED. // ADD OTHER STATE LIKE THE LOGGER IF NEEDED.
} }
type ProjectRepository interface {
ReadByID(ctx context.Context, claims auth.Claims, id string) (*project.Project, error)
Find(ctx context.Context, claims auth.Claims, req project.ProjectFindRequest) (project.Projects, error)
Read(ctx context.Context, claims auth.Claims, req project.ProjectReadRequest) (*project.Project, error)
Create(ctx context.Context, claims auth.Claims, req project.ProjectCreateRequest, now time.Time) (*project.Project, error)
Update(ctx context.Context, claims auth.Claims, req project.ProjectUpdateRequest, now time.Time) error
Archive(ctx context.Context, claims auth.Claims, req project.ProjectArchiveRequest, now time.Time) error
Delete(ctx context.Context, claims auth.Claims, req project.ProjectDeleteRequest) error
}
// Find godoc // Find godoc
// TODO: Need to implement unittests on projects/find endpoint. There are none. // TODO: Need to implement unittests on projects/find endpoint. There are none.
// @Summary List projects // @Summary List projects
@ -40,7 +52,7 @@ type Project struct {
// @Failure 403 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /projects [get] // @Router /projects [get]
func (h *Project) Find(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Projects) Find(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
claims, ok := ctx.Value(auth.Key).(auth.Claims) claims, ok := ctx.Value(auth.Key).(auth.Claims)
if !ok { if !ok {
return errors.New("claims missing from context") return errors.New("claims missing from context")
@ -133,7 +145,7 @@ func (h *Project) Find(ctx context.Context, w http.ResponseWriter, r *http.Reque
// @Failure 404 {object} weberror.ErrorResponse // @Failure 404 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /projects/{id} [get] // @Router /projects/{id} [get]
func (h *Project) Read(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Projects) Read(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
claims, ok := ctx.Value(auth.Key).(auth.Claims) claims, ok := ctx.Value(auth.Key).(auth.Claims)
if !ok { if !ok {
return errors.New("claims missing from context") return errors.New("claims missing from context")
@ -181,7 +193,7 @@ func (h *Project) Read(ctx context.Context, w http.ResponseWriter, r *http.Reque
// @Failure 404 {object} weberror.ErrorResponse // @Failure 404 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /projects [post] // @Router /projects [post]
func (h *Project) Create(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Projects) Create(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
v, err := webcontext.ContextValues(ctx) v, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {
return err return err
@ -231,7 +243,7 @@ func (h *Project) Create(ctx context.Context, w http.ResponseWriter, r *http.Req
// @Failure 403 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /projects [patch] // @Router /projects [patch]
func (h *Project) Update(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Projects) Update(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
v, err := webcontext.ContextValues(ctx) v, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {
return err return err
@ -282,7 +294,7 @@ func (h *Project) Update(ctx context.Context, w http.ResponseWriter, r *http.Req
// @Failure 403 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /projects/archive [patch] // @Router /projects/archive [patch]
func (h *Project) Archive(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Projects) Archive(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
v, err := webcontext.ContextValues(ctx) v, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {
return err return err
@ -333,7 +345,7 @@ func (h *Project) Archive(ctx context.Context, w http.ResponseWriter, r *http.Re
// @Failure 403 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /projects/{id} [delete] // @Router /projects/{id} [delete]
func (h *Project) Delete(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Projects) Delete(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
claims, err := auth.ClaimsFromContext(ctx) claims, err := auth.ClaimsFromContext(ctx)
if err != nil { if err != nil {
return err return err

View File

@ -5,21 +5,14 @@ import (
"net/http" "net/http"
"os" "os"
"geeks-accelerator/oss/saas-starter-kit/internal/account"
"geeks-accelerator/oss/saas-starter-kit/internal/account/account_preference"
"geeks-accelerator/oss/saas-starter-kit/internal/mid" "geeks-accelerator/oss/saas-starter-kit/internal/mid"
saasSwagger "geeks-accelerator/oss/saas-starter-kit/internal/mid/saas-swagger" saasSwagger "geeks-accelerator/oss/saas-starter-kit/internal/mid/saas-swagger"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
_ "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" _ "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"geeks-accelerator/oss/saas-starter-kit/internal/project"
"geeks-accelerator/oss/saas-starter-kit/internal/signup"
_ "geeks-accelerator/oss/saas-starter-kit/internal/signup" _ "geeks-accelerator/oss/saas-starter-kit/internal/signup"
"geeks-accelerator/oss/saas-starter-kit/internal/user"
"geeks-accelerator/oss/saas-starter-kit/internal/user_account"
"geeks-accelerator/oss/saas-starter-kit/internal/user_account/invite"
"geeks-accelerator/oss/saas-starter-kit/internal/user_auth"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis" "gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis"
) )
@ -29,14 +22,14 @@ type AppContext struct {
Env webcontext.Env Env webcontext.Env
MasterDB *sqlx.DB MasterDB *sqlx.DB
Redis *redis.Client Redis *redis.Client
UserRepo *user.Repository UserRepo UserRepository
UserAccountRepo *user_account.Repository UserAccountRepo UserAccountRepository
AccountRepo *account.Repository AccountRepo AccountRepository
AccountPrefRepo *account_preference.Repository AccountPrefRepo AccountPrefRepository
AuthRepo *user_auth.Repository AuthRepo UserAuthRepository
SignupRepo *signup.Repository SignupRepo SignupRepository
InviteRepo *invite.Repository InviteRepo UserInviteRepository
ProjectRepo *project.Repository ProjectRepo ProjectRepository
Authenticator *auth.Authenticator Authenticator *auth.Authenticator
PreAppMiddleware []web.Middleware PreAppMiddleware []web.Middleware
PostAppMiddleware []web.Middleware PostAppMiddleware []web.Middleware
@ -79,9 +72,9 @@ func API(shutdown chan os.Signal, appCtx *AppContext) http.Handler {
app.Handle("GET", "/v1/examples/error-response", ex.ErrorResponse) app.Handle("GET", "/v1/examples/error-response", ex.ErrorResponse)
// Register user management and authentication endpoints. // Register user management and authentication endpoints.
u := User{ u := Users{
Repository: appCtx.UserRepo, UserRepo: appCtx.UserRepo,
Auth: appCtx.AuthRepo, AuthRepo: appCtx.AuthRepo,
} }
app.Handle("GET", "/v1/users", u.Find, mid.AuthenticateHeader(appCtx.Authenticator)) app.Handle("GET", "/v1/users", u.Find, mid.AuthenticateHeader(appCtx.Authenticator))
app.Handle("POST", "/v1/users", u.Create, mid.AuthenticateHeader(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) app.Handle("POST", "/v1/users", u.Create, mid.AuthenticateHeader(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin))
@ -107,7 +100,7 @@ func API(shutdown chan os.Signal, appCtx *AppContext) http.Handler {
app.Handle("DELETE", "/v1/user_accounts", ua.Delete, mid.AuthenticateHeader(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) app.Handle("DELETE", "/v1/user_accounts", ua.Delete, mid.AuthenticateHeader(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin))
// Register account endpoints. // Register account endpoints.
a := Account{ a := Accounts{
Repository: appCtx.AccountRepo, Repository: appCtx.AccountRepo,
} }
app.Handle("GET", "/v1/accounts/:id", a.Read, mid.AuthenticateHeader(appCtx.Authenticator)) app.Handle("GET", "/v1/accounts/:id", a.Read, mid.AuthenticateHeader(appCtx.Authenticator))
@ -120,7 +113,7 @@ func API(shutdown chan os.Signal, appCtx *AppContext) http.Handler {
app.Handle("POST", "/v1/signup", s.Signup) app.Handle("POST", "/v1/signup", s.Signup)
// Register project. // Register project.
p := Project{ p := Projects{
Repository: appCtx.ProjectRepo, Repository: appCtx.ProjectRepo,
} }
app.Handle("GET", "/v1/projects", p.Find, mid.AuthenticateHeader(appCtx.Authenticator)) app.Handle("GET", "/v1/projects", p.Find, mid.AuthenticateHeader(appCtx.Authenticator))

View File

@ -3,6 +3,7 @@ package handlers
import ( import (
"context" "context"
"net/http" "net/http"
"time"
"geeks-accelerator/oss/saas-starter-kit/internal/account" "geeks-accelerator/oss/saas-starter-kit/internal/account"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth"
@ -10,17 +11,22 @@ import (
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"geeks-accelerator/oss/saas-starter-kit/internal/signup" "geeks-accelerator/oss/saas-starter-kit/internal/signup"
"github.com/pkg/errors" "github.com/pkg/errors"
"gopkg.in/go-playground/validator.v9" "gopkg.in/go-playground/validator.v9"
) )
// Signup represents the Signup API method handler set. // Signup represents the Signup API method handler set.
type Signup struct { type Signup struct {
*signup.Repository Repository SignupRepository
// ADD OTHER STATE LIKE THE LOGGER AND CONFIG HERE. // ADD OTHER STATE LIKE THE LOGGER AND CONFIG HERE.
} }
type SignupRepository interface {
Signup(ctx context.Context, claims auth.Claims, req signup.SignupRequest, now time.Time) (*signup.SignupResult, error)
}
// Signup godoc // Signup godoc
// @Summary Signup handles new account creation. // @Summary Signup handles new account creation.
// @Description Signup creates a new account and user in the system. // @Description Signup creates a new account and user in the system.

View File

@ -13,6 +13,7 @@ import (
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"geeks-accelerator/oss/saas-starter-kit/internal/user" "geeks-accelerator/oss/saas-starter-kit/internal/user"
"geeks-accelerator/oss/saas-starter-kit/internal/user_auth" "geeks-accelerator/oss/saas-starter-kit/internal/user_auth"
"github.com/gorilla/schema" "github.com/gorilla/schema"
"github.com/pkg/errors" "github.com/pkg/errors"
"gopkg.in/go-playground/validator.v9" "gopkg.in/go-playground/validator.v9"
@ -22,13 +23,36 @@ import (
var sessionTtl = time.Hour * 24 var sessionTtl = time.Hour * 24
// User represents the User API method handler set. // User represents the User API method handler set.
type User struct { type Users struct {
*user.Repository AuthRepo UserAuthRepository
Auth *user_auth.Repository UserRepo UserRepository
// ADD OTHER STATE LIKE THE LOGGER AND CONFIG HERE. // ADD OTHER STATE LIKE THE LOGGER AND CONFIG HERE.
} }
type UserAuthRepository interface {
SwitchAccount(ctx context.Context, claims auth.Claims, req user_auth.SwitchAccountRequest, expires time.Duration,
now time.Time, scopes ...string) (user_auth.Token, error)
Authenticate(ctx context.Context, req user_auth.AuthenticateRequest, expires time.Duration, now time.Time, scopes ...string) (user_auth.Token, error)
VirtualLogin(ctx context.Context, claims auth.Claims, req user_auth.VirtualLoginRequest,
expires time.Duration, now time.Time, scopes ...string) (user_auth.Token, error)
VirtualLogout(ctx context.Context, claims auth.Claims, expires time.Duration, now time.Time, scopes ...string) (user_auth.Token, error)
}
type UserRepository interface {
Find(ctx context.Context, claims auth.Claims, req user.UserFindRequest) (user.Users, error)
//FindByAccount(ctx context.Context, claims auth.Claims, req user.UserFindByAccountRequest) (user.Users, error)
Read(ctx context.Context, claims auth.Claims, req user.UserReadRequest) (*user.User, error)
ReadByID(ctx context.Context, claims auth.Claims, id string) (*user.User, error)
Create(ctx context.Context, claims auth.Claims, req user.UserCreateRequest, now time.Time) (*user.User, error)
Update(ctx context.Context, claims auth.Claims, req user.UserUpdateRequest, now time.Time) error
UpdatePassword(ctx context.Context, claims auth.Claims, req user.UserUpdatePasswordRequest, now time.Time) error
Archive(ctx context.Context, claims auth.Claims, req user.UserArchiveRequest, now time.Time) error
Restore(ctx context.Context, claims auth.Claims, req user.UserRestoreRequest, now time.Time) error
Delete(ctx context.Context, claims auth.Claims, req user.UserDeleteRequest) error
ResetPassword(ctx context.Context, req user.UserResetPasswordRequest, now time.Time) (string, error)
ResetConfirm(ctx context.Context, req user.UserResetConfirmRequest, now time.Time) (*user.User, error)
}
// Find godoc // Find godoc
// TODO: Need to implement unittests on users/find endpoint. There are none. // TODO: Need to implement unittests on users/find endpoint. There are none.
// @Summary List users // @Summary List users
@ -46,7 +70,7 @@ type User struct {
// @Failure 400 {object} weberror.ErrorResponse // @Failure 400 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /users [get] // @Router /users [get]
func (h *User) Find(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Users) Find(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
claims, ok := ctx.Value(auth.Key).(auth.Claims) claims, ok := ctx.Value(auth.Key).(auth.Claims)
if !ok { if !ok {
return errors.New("claims missing from context") return errors.New("claims missing from context")
@ -113,7 +137,7 @@ func (h *User) Find(ctx context.Context, w http.ResponseWriter, r *http.Request,
// return web.RespondJsonError(ctx, w, err) // return web.RespondJsonError(ctx, w, err)
//} //}
res, err := h.Repository.Find(ctx, claims, req) res, err := h.UserRepo.Find(ctx, claims, req)
if err != nil { if err != nil {
return err return err
} }
@ -139,7 +163,7 @@ func (h *User) Find(ctx context.Context, w http.ResponseWriter, r *http.Request,
// @Failure 404 {object} weberror.ErrorResponse // @Failure 404 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /users/{id} [get] // @Router /users/{id} [get]
func (h *User) Read(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Users) Read(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
claims, ok := ctx.Value(auth.Key).(auth.Claims) claims, ok := ctx.Value(auth.Key).(auth.Claims)
if !ok { if !ok {
return errors.New("claims missing from context") return errors.New("claims missing from context")
@ -156,7 +180,7 @@ func (h *User) Read(ctx context.Context, w http.ResponseWriter, r *http.Request,
includeArchived = b includeArchived = b
} }
res, err := h.Repository.Read(ctx, claims, user.UserReadRequest{ res, err := h.UserRepo.Read(ctx, claims, user.UserReadRequest{
ID: params["id"], ID: params["id"],
IncludeArchived: includeArchived, IncludeArchived: includeArchived,
}) })
@ -186,7 +210,7 @@ func (h *User) Read(ctx context.Context, w http.ResponseWriter, r *http.Request,
// @Failure 403 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /users [post] // @Router /users [post]
func (h *User) Create(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Users) Create(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
v, err := webcontext.ContextValues(ctx) v, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {
return err return err
@ -205,7 +229,7 @@ func (h *User) Create(ctx context.Context, w http.ResponseWriter, r *http.Reques
return web.RespondJsonError(ctx, w, err) return web.RespondJsonError(ctx, w, err)
} }
res, err := h.Repository.Create(ctx, claims, req, v.Now) usr, err := h.UserRepo.Create(ctx, claims, req, v.Now)
if err != nil { if err != nil {
cause := errors.Cause(err) cause := errors.Cause(err)
switch cause { switch cause {
@ -221,7 +245,7 @@ func (h *User) Create(ctx context.Context, w http.ResponseWriter, r *http.Reques
} }
} }
return web.RespondJson(ctx, w, res.Response(ctx), http.StatusCreated) return web.RespondJson(ctx, w, usr.Response(ctx), http.StatusCreated)
} }
// Read godoc // Read godoc
@ -237,7 +261,7 @@ func (h *User) Create(ctx context.Context, w http.ResponseWriter, r *http.Reques
// @Failure 403 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /users [patch] // @Router /users [patch]
func (h *User) Update(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Users) Update(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
v, err := webcontext.ContextValues(ctx) v, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {
return err return err
@ -256,7 +280,7 @@ func (h *User) Update(ctx context.Context, w http.ResponseWriter, r *http.Reques
return web.RespondJsonError(ctx, w, err) return web.RespondJsonError(ctx, w, err)
} }
err = h.Repository.Update(ctx, claims, req, v.Now) err = h.UserRepo.Update(ctx, claims, req, v.Now)
if err != nil { if err != nil {
cause := errors.Cause(err) cause := errors.Cause(err)
switch cause { switch cause {
@ -288,7 +312,7 @@ func (h *User) Update(ctx context.Context, w http.ResponseWriter, r *http.Reques
// @Failure 403 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /users/password [patch] // @Router /users/password [patch]
func (h *User) UpdatePassword(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Users) UpdatePassword(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
v, err := webcontext.ContextValues(ctx) v, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {
return err return err
@ -307,7 +331,7 @@ func (h *User) UpdatePassword(ctx context.Context, w http.ResponseWriter, r *htt
return web.RespondJsonError(ctx, w, err) return web.RespondJsonError(ctx, w, err)
} }
err = h.Repository.UpdatePassword(ctx, claims, req, v.Now) err = h.UserRepo.UpdatePassword(ctx, claims, req, v.Now)
if err != nil { if err != nil {
cause := errors.Cause(err) cause := errors.Cause(err)
switch cause { switch cause {
@ -341,7 +365,7 @@ func (h *User) UpdatePassword(ctx context.Context, w http.ResponseWriter, r *htt
// @Failure 403 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /users/archive [patch] // @Router /users/archive [patch]
func (h *User) Archive(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Users) Archive(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
v, err := webcontext.ContextValues(ctx) v, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {
return err return err
@ -360,7 +384,7 @@ func (h *User) Archive(ctx context.Context, w http.ResponseWriter, r *http.Reque
return web.RespondJsonError(ctx, w, err) return web.RespondJsonError(ctx, w, err)
} }
err = h.Repository.Archive(ctx, claims, req, v.Now) err = h.UserRepo.Archive(ctx, claims, req, v.Now)
if err != nil { if err != nil {
cause := errors.Cause(err) cause := errors.Cause(err)
switch cause { switch cause {
@ -392,13 +416,13 @@ func (h *User) Archive(ctx context.Context, w http.ResponseWriter, r *http.Reque
// @Failure 403 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /users/{id} [delete] // @Router /users/{id} [delete]
func (h *User) Delete(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Users) Delete(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
claims, err := auth.ClaimsFromContext(ctx) claims, err := auth.ClaimsFromContext(ctx)
if err != nil { if err != nil {
return err return err
} }
err = h.Repository.Delete(ctx, claims, err = h.UserRepo.Delete(ctx, claims,
user.UserDeleteRequest{ID: params["id"]}) user.UserDeleteRequest{ID: params["id"]})
if err != nil { if err != nil {
cause := errors.Cause(err) cause := errors.Cause(err)
@ -431,7 +455,7 @@ func (h *User) Delete(ctx context.Context, w http.ResponseWriter, r *http.Reques
// @Failure 401 {object} weberror.ErrorResponse // @Failure 401 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /users/switch-account/{account_id} [patch] // @Router /users/switch-account/{account_id} [patch]
func (h *User) SwitchAccount(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Users) SwitchAccount(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
v, err := webcontext.ContextValues(ctx) v, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {
return err return err
@ -442,7 +466,7 @@ func (h *User) SwitchAccount(ctx context.Context, w http.ResponseWriter, r *http
return err return err
} }
tkn, err := h.Auth.SwitchAccount(ctx, claims, user_auth.SwitchAccountRequest{ tkn, err := h.AuthRepo.SwitchAccount(ctx, claims, user_auth.SwitchAccountRequest{
AccountID: params["account_id"], AccountID: params["account_id"],
}, sessionTtl, v.Now) }, sessionTtl, v.Now)
if err != nil { if err != nil {
@ -478,7 +502,7 @@ func (h *User) SwitchAccount(ctx context.Context, w http.ResponseWriter, r *http
// @Failure 401 {object} weberror.ErrorResponse // @Failure 401 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse
// @Router /oauth/token [post] // @Router /oauth/token [post]
func (h *User) Token(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *Users) Token(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
v, err := webcontext.ContextValues(ctx) v, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {
return err return err
@ -533,7 +557,7 @@ func (h *User) Token(ctx context.Context, w http.ResponseWriter, r *http.Request
scopes = strings.Split(qv, ",") scopes = strings.Split(qv, ",")
} }
tkn, err := h.Auth.Authenticate(ctx, authReq, sessionTtl, v.Now, scopes...) tkn, err := h.AuthRepo.Authenticate(ctx, authReq, sessionTtl, v.Now, scopes...)
if err != nil { if err != nil {
cause := errors.Cause(err) cause := errors.Cause(err)
switch cause { switch cause {

View File

@ -5,23 +5,44 @@ import (
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
"time"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"geeks-accelerator/oss/saas-starter-kit/internal/user_account" "geeks-accelerator/oss/saas-starter-kit/internal/user_account"
"geeks-accelerator/oss/saas-starter-kit/internal/user_account/invite"
"github.com/pkg/errors" "github.com/pkg/errors"
"gopkg.in/go-playground/validator.v9" "gopkg.in/go-playground/validator.v9"
) )
// UserAccount represents the UserAccount API method handler set. // UserAccount represents the UserAccount API method handler set.
type UserAccount struct { type UserAccount struct {
*user_account.Repository UserInvite UserInviteRepository
Repository UserAccountRepository
// ADD OTHER STATE LIKE THE LOGGER AND CONFIG HERE. // ADD OTHER STATE LIKE THE LOGGER AND CONFIG HERE.
} }
type UserAccountRepository interface {
Find(ctx context.Context, claims auth.Claims, req user_account.UserAccountFindRequest) (user_account.UserAccounts, error)
FindByUserID(ctx context.Context, claims auth.Claims, userID string, includedArchived bool) (user_account.UserAccounts, error)
UserFindByAccount(ctx context.Context, claims auth.Claims, req user_account.UserFindByAccountRequest) (user_account.Users, error)
Create(ctx context.Context, claims auth.Claims, req user_account.UserAccountCreateRequest, now time.Time) (*user_account.UserAccount, error)
Read(ctx context.Context, claims auth.Claims, req user_account.UserAccountReadRequest) (*user_account.UserAccount, error)
Update(ctx context.Context, claims auth.Claims, req user_account.UserAccountUpdateRequest, now time.Time) error
Archive(ctx context.Context, claims auth.Claims, req user_account.UserAccountArchiveRequest, now time.Time) error
Delete(ctx context.Context, claims auth.Claims, req user_account.UserAccountDeleteRequest) error
}
type UserInviteRepository interface {
SendUserInvites(ctx context.Context, claims auth.Claims, req invite.SendUserInvitesRequest, now time.Time) ([]string, error)
AcceptInvite(ctx context.Context, req invite.AcceptInviteRequest, now time.Time) (*user_account.UserAccount, error)
AcceptInviteUser(ctx context.Context, req invite.AcceptInviteUserRequest, now time.Time) (*user_account.UserAccount, error)
}
// Find godoc // Find godoc
// TODO: Need to implement unittests on user_accounts/find endpoint. There are none. // TODO: Need to implement unittests on user_accounts/find endpoint. There are none.
// @Summary List user accounts // @Summary List user accounts

View File

@ -35,6 +35,7 @@ import (
"geeks-accelerator/oss/saas-starter-kit/internal/user_account" "geeks-accelerator/oss/saas-starter-kit/internal/user_account"
"geeks-accelerator/oss/saas-starter-kit/internal/user_account/invite" "geeks-accelerator/oss/saas-starter-kit/internal/user_account/invite"
"geeks-accelerator/oss/saas-starter-kit/internal/user_auth" "geeks-accelerator/oss/saas-starter-kit/internal/user_auth"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/ec2metadata" "github.com/aws/aws-sdk-go/aws/ec2metadata"
@ -435,7 +436,7 @@ func main() {
projectRoute, err := project_route.New(cfg.Service.BaseUrl, cfg.Project.WebAppBaseUrl) projectRoute, err := project_route.New(cfg.Service.BaseUrl, cfg.Project.WebAppBaseUrl)
if err != nil { if err != nil {
log.Fatalf("main : project routes : %+v", cfg.Service.BaseUrl, err) log.Fatalf("main : project routes : %s: %+v", cfg.Service.BaseUrl, err)
} }
usrRepo := user.NewRepository(masterDb, projectRoute.UserResetPassword, notifyEmail, cfg.Project.SharedSecretKey) usrRepo := user.NewRepository(masterDb, projectRoute.UserResetPassword, notifyEmail, cfg.Project.SharedSecretKey)

View File

@ -13,6 +13,7 @@ import (
"geeks-accelerator/oss/saas-starter-kit/internal/platform/tests" "geeks-accelerator/oss/saas-starter-kit/internal/platform/tests"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"github.com/pborman/uuid" "github.com/pborman/uuid"
) )

View File

@ -2,9 +2,7 @@ package handlers
import ( import (
"context" "context"
"net/http" "geeks-accelerator/oss/saas-starter-kit/cmd/web-api/handlers"
"time"
"geeks-accelerator/oss/saas-starter-kit/internal/account" "geeks-accelerator/oss/saas-starter-kit/internal/account"
"geeks-accelerator/oss/saas-starter-kit/internal/account/account_preference" "geeks-accelerator/oss/saas-starter-kit/internal/account/account_preference"
"geeks-accelerator/oss/saas-starter-kit/internal/geonames" "geeks-accelerator/oss/saas-starter-kit/internal/geonames"
@ -12,19 +10,21 @@ import (
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"geeks-accelerator/oss/saas-starter-kit/internal/user_auth"
"net/http"
"time"
"github.com/gorilla/schema" "github.com/gorilla/schema"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// Account represents the Account API method handler set. // Account represents the Account API method handler set.
type Account struct { type Account struct {
AccountRepo *account.Repository AccountRepo handlers.AccountRepository
AccountPrefRepo *account_preference.Repository AccountPrefRepo handlers.AccountPrefRepository
AuthRepo *user_auth.Repository AuthRepo handlers.UserAuthRepository
GeoRepo GeoRepository
Authenticator *auth.Authenticator Authenticator *auth.Authenticator
MasterDB *sqlx.DB
Renderer web.Renderer Renderer web.Renderer
} }
@ -248,14 +248,14 @@ func (h *Account) Update(ctx context.Context, w http.ResponseWriter, r *http.Req
data["account"] = acc.Response(ctx) data["account"] = acc.Response(ctx)
data["timezones"], err = geonames.ListTimezones(ctx, h.MasterDB) data["timezones"], err = h.GeoRepo.ListTimezones(ctx)
if err != nil { if err != nil {
return false, err return false, err
} }
data["geonameCountries"] = geonames.ValidGeonameCountries(ctx) data["geonameCountries"] = geonames.ValidGeonameCountries(ctx)
data["countries"], err = geonames.FindCountries(ctx, h.MasterDB, "name", "") data["countries"], err = h.GeoRepo.FindCountries(ctx, "name", "")
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@ -8,14 +8,25 @@ import (
"geeks-accelerator/oss/saas-starter-kit/internal/geonames" "geeks-accelerator/oss/saas-starter-kit/internal/geonames"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web"
"github.com/jmoiron/sqlx"
//"github.com/jmoiron/sqlx"
"gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis" "gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis"
) )
// Check provides support for orchestration geo endpoints. // Check provides support for orchestration geo endpoints.
type Geo struct { type Geo struct {
MasterDB *sqlx.DB
Redis *redis.Client Redis *redis.Client
GeoRepo GeoRepository
}
type GeoRepository interface {
FindGeonames(ctx context.Context, orderBy, where string, args ...interface{}) ([]*geonames.Geoname, error)
FindGeonamePostalCodes(ctx context.Context, where string, args ...interface{}) ([]string, error)
FindGeonameRegions(ctx context.Context, orderBy, where string, args ...interface{}) ([]*geonames.Region, error)
FindCountries(ctx context.Context, orderBy, where string, args ...interface{}) ([]*geonames.Country, error)
FindCountryTimezones(ctx context.Context, orderBy, where string, args ...interface{}) ([]*geonames.CountryTimezone, error)
ListTimezones(ctx context.Context) ([]string, error)
LoadGeonames(ctx context.Context, rr chan<- interface{}, countries ...string)
} }
// GeonameByPostalCode... // GeonameByPostalCode...
@ -39,7 +50,7 @@ func (h *Geo) GeonameByPostalCode(ctx context.Context, w http.ResponseWriter, r
where := strings.Join(filters, " AND ") where := strings.Join(filters, " AND ")
res, err := geonames.FindGeonames(ctx, h.MasterDB, "postal_code", where, args...) res, err := h.GeoRepo.FindGeonames(ctx, "postal_code", where, args...)
if err != nil { if err != nil {
fmt.Printf("%+v", err) fmt.Printf("%+v", err)
return web.RespondJsonError(ctx, w, err) return web.RespondJsonError(ctx, w, err)
@ -74,7 +85,7 @@ func (h *Geo) PostalCodesAutocomplete(ctx context.Context, w http.ResponseWriter
where := strings.Join(filters, " AND ") where := strings.Join(filters, " AND ")
res, err := geonames.FindGeonamePostalCodes(ctx, h.MasterDB, where, args...) res, err := h.GeoRepo.FindGeonamePostalCodes(ctx, where, args...)
if err != nil { if err != nil {
return web.RespondJsonError(ctx, w, err) return web.RespondJsonError(ctx, w, err)
} }
@ -101,7 +112,7 @@ func (h *Geo) RegionsAutocomplete(ctx context.Context, w http.ResponseWriter, r
where := strings.Join(filters, " AND ") where := strings.Join(filters, " AND ")
res, err := geonames.FindGeonameRegions(ctx, h.MasterDB, "state_name", where, args...) res, err := h.GeoRepo.FindGeonameRegions(ctx, "state_name", where, args...)
if err != nil { if err != nil {
fmt.Printf("%+v", err) fmt.Printf("%+v", err)
return web.RespondJsonError(ctx, w, err) return web.RespondJsonError(ctx, w, err)
@ -144,7 +155,7 @@ func (h *Geo) CountryTimezones(ctx context.Context, w http.ResponseWriter, r *ht
where := strings.Join(filters, " AND ") where := strings.Join(filters, " AND ")
res, err := geonames.FindCountryTimezones(ctx, h.MasterDB, "timezone_id", where, args...) res, err := h.GeoRepo.FindCountryTimezones(ctx, "timezone_id", where, args...)
if err != nil { if err != nil {
return web.RespondJsonError(ctx, w, err) return web.RespondJsonError(ctx, w, err)
} }

View File

@ -3,6 +3,7 @@ package handlers
import ( import (
"context" "context"
"fmt" "fmt"
"geeks-accelerator/oss/saas-starter-kit/cmd/web-api/handlers"
"net/http" "net/http"
"strings" "strings"
@ -12,6 +13,7 @@ import (
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"geeks-accelerator/oss/saas-starter-kit/internal/project" "geeks-accelerator/oss/saas-starter-kit/internal/project"
"github.com/gorilla/schema" "github.com/gorilla/schema"
"github.com/pkg/errors" "github.com/pkg/errors"
"gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis" "gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis"
@ -19,7 +21,7 @@ import (
// Projects represents the Projects API method handler set. // Projects represents the Projects API method handler set.
type Projects struct { type Projects struct {
ProjectRepo *project.Repository ProjectRepo handlers.ProjectRepository
Redis *redis.Client Redis *redis.Client
Renderer web.Renderer Renderer web.Renderer
} }

View File

@ -9,20 +9,23 @@ import (
"path/filepath" "path/filepath"
"time" "time"
"geeks-accelerator/oss/saas-starter-kit/internal/account" "geeks-accelerator/oss/saas-starter-kit/cmd/web-api/handlers"
"geeks-accelerator/oss/saas-starter-kit/internal/account/account_preference" //"geeks-accelerator/oss/saas-starter-kit/internal/account"
//"geeks-accelerator/oss/saas-starter-kit/internal/account/account_preference"
"geeks-accelerator/oss/saas-starter-kit/internal/mid" "geeks-accelerator/oss/saas-starter-kit/internal/mid"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"geeks-accelerator/oss/saas-starter-kit/internal/project"
//"geeks-accelerator/oss/saas-starter-kit/internal/project"
"geeks-accelerator/oss/saas-starter-kit/internal/project_route" "geeks-accelerator/oss/saas-starter-kit/internal/project_route"
"geeks-accelerator/oss/saas-starter-kit/internal/signup" // "geeks-accelerator/oss/saas-starter-kit/internal/signup"
"geeks-accelerator/oss/saas-starter-kit/internal/user" // "geeks-accelerator/oss/saas-starter-kit/internal/user"
"geeks-accelerator/oss/saas-starter-kit/internal/user_account" // "geeks-accelerator/oss/saas-starter-kit/internal/user_account"
"geeks-accelerator/oss/saas-starter-kit/internal/user_account/invite" // "geeks-accelerator/oss/saas-starter-kit/internal/user_account/invite"
"geeks-accelerator/oss/saas-starter-kit/internal/user_auth" // "geeks-accelerator/oss/saas-starter-kit/internal/user_auth"
"github.com/ikeikeikeike/go-sitemap-generator/v2/stm" "github.com/ikeikeikeike/go-sitemap-generator/v2/stm"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis" "gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis"
@ -39,14 +42,15 @@ type AppContext struct {
Env webcontext.Env Env webcontext.Env
MasterDB *sqlx.DB MasterDB *sqlx.DB
Redis *redis.Client Redis *redis.Client
UserRepo *user.Repository UserRepo handlers.UserRepository
UserAccountRepo *user_account.Repository UserAccountRepo handlers.UserAccountRepository
AccountRepo *account.Repository AccountRepo handlers.AccountRepository
AccountPrefRepo *account_preference.Repository AccountPrefRepo handlers.AccountPrefRepository
AuthRepo *user_auth.Repository AuthRepo handlers.UserAuthRepository
SignupRepo *signup.Repository SignupRepo handlers.SignupRepository
InviteRepo *invite.Repository InviteRepo handlers.UserInviteRepository
ProjectRepo *project.Repository ProjectRepo handlers.ProjectRepository
GeoRepo GeoRepository
Authenticator *auth.Authenticator Authenticator *auth.Authenticator
StaticDir string StaticDir string
TemplateDir string TemplateDir string
@ -117,7 +121,7 @@ func APP(shutdown chan os.Signal, appCtx *AppContext) http.Handler {
UserAccountRepo: appCtx.UserAccountRepo, UserAccountRepo: appCtx.UserAccountRepo,
AuthRepo: appCtx.AuthRepo, AuthRepo: appCtx.AuthRepo,
InviteRepo: appCtx.InviteRepo, InviteRepo: appCtx.InviteRepo,
MasterDB: appCtx.MasterDB, GeoRepo: appCtx.GeoRepo,
Redis: appCtx.Redis, Redis: appCtx.Redis,
Renderer: appCtx.Renderer, Renderer: appCtx.Renderer,
} }
@ -134,12 +138,12 @@ func APP(shutdown chan os.Signal, appCtx *AppContext) http.Handler {
app.Handle("GET", "/users", us.Index, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasAuth()) app.Handle("GET", "/users", us.Index, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasAuth())
// Register user management and authentication endpoints. // Register user management and authentication endpoints.
u := User{ u := UserRepos{
UserRepo: appCtx.UserRepo, UserRepo: appCtx.UserRepo,
UserAccountRepo: appCtx.UserAccountRepo, UserAccountRepo: appCtx.UserAccountRepo,
AccountRepo: appCtx.AccountRepo, AccountRepo: appCtx.AccountRepo,
AuthRepo: appCtx.AuthRepo, AuthRepo: appCtx.AuthRepo,
MasterDB: appCtx.MasterDB, GeoRepo: appCtx.GeoRepo,
Renderer: appCtx.Renderer, Renderer: appCtx.Renderer,
} }
app.Handle("POST", "/user/login", u.Login) app.Handle("POST", "/user/login", u.Login)
@ -168,7 +172,7 @@ func APP(shutdown chan os.Signal, appCtx *AppContext) http.Handler {
AccountPrefRepo: appCtx.AccountPrefRepo, AccountPrefRepo: appCtx.AccountPrefRepo,
AuthRepo: appCtx.AuthRepo, AuthRepo: appCtx.AuthRepo,
Authenticator: appCtx.Authenticator, Authenticator: appCtx.Authenticator,
MasterDB: appCtx.MasterDB, GeoRepo: appCtx.GeoRepo,
Renderer: appCtx.Renderer, Renderer: appCtx.Renderer,
} }
app.Handle("POST", "/account/update", acc.Update, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) app.Handle("POST", "/account/update", acc.Update, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin))
@ -180,7 +184,7 @@ func APP(shutdown chan os.Signal, appCtx *AppContext) http.Handler {
s := Signup{ s := Signup{
SignupRepo: appCtx.SignupRepo, SignupRepo: appCtx.SignupRepo,
AuthRepo: appCtx.AuthRepo, AuthRepo: appCtx.AuthRepo,
MasterDB: appCtx.MasterDB, GeoRepo: appCtx.GeoRepo,
Renderer: appCtx.Renderer, Renderer: appCtx.Renderer,
} }
// This route is not authenticated // This route is not authenticated
@ -197,7 +201,7 @@ func APP(shutdown chan os.Signal, appCtx *AppContext) http.Handler {
// Register geo // Register geo
g := Geo{ g := Geo{
MasterDB: appCtx.MasterDB, GeoRepo: appCtx.GeoRepo,
Redis: appCtx.Redis, Redis: appCtx.Redis,
} }
app.Handle("GET", "/geo/regions/autocomplete", g.RegionsAutocomplete) app.Handle("GET", "/geo/regions/autocomplete", g.RegionsAutocomplete)

View File

@ -2,6 +2,7 @@ package handlers
import ( import (
"context" "context"
"geeks-accelerator/oss/saas-starter-kit/cmd/web-api/handlers"
"net/http" "net/http"
"time" "time"
@ -13,6 +14,7 @@ import (
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"geeks-accelerator/oss/saas-starter-kit/internal/signup" "geeks-accelerator/oss/saas-starter-kit/internal/signup"
"geeks-accelerator/oss/saas-starter-kit/internal/user_auth" "geeks-accelerator/oss/saas-starter-kit/internal/user_auth"
"github.com/gorilla/schema" "github.com/gorilla/schema"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -20,8 +22,9 @@ import (
// Signup represents the Signup API method handler set. // Signup represents the Signup API method handler set.
type Signup struct { type Signup struct {
SignupRepo *signup.Repository SignupRepo handlers.SignupRepository
AuthRepo *user_auth.Repository AuthRepo handlers.UserAuthRepository
GeoRepo GeoRepository
MasterDB *sqlx.DB MasterDB *sqlx.DB
Renderer web.Renderer Renderer web.Renderer
} }
@ -108,7 +111,7 @@ func (h *Signup) Step1(ctx context.Context, w http.ResponseWriter, r *http.Reque
data["geonameCountries"] = geonames.ValidGeonameCountries(ctx) data["geonameCountries"] = geonames.ValidGeonameCountries(ctx)
data["countries"], err = geonames.FindCountries(ctx, h.MasterDB, "name", "") data["countries"], err = h.GeoRepo.FindCountries(ctx, "name", "")
if err != nil { if err != nil {
return err return err
} }

View File

@ -8,8 +8,9 @@ import (
"strings" "strings"
"time" "time"
"geeks-accelerator/oss/saas-starter-kit/cmd/web-api/handlers"
"geeks-accelerator/oss/saas-starter-kit/internal/account" "geeks-accelerator/oss/saas-starter-kit/internal/account"
"geeks-accelerator/oss/saas-starter-kit/internal/geonames"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
@ -17,6 +18,7 @@ import (
"geeks-accelerator/oss/saas-starter-kit/internal/user" "geeks-accelerator/oss/saas-starter-kit/internal/user"
"geeks-accelerator/oss/saas-starter-kit/internal/user_account" "geeks-accelerator/oss/saas-starter-kit/internal/user_account"
"geeks-accelerator/oss/saas-starter-kit/internal/user_auth" "geeks-accelerator/oss/saas-starter-kit/internal/user_auth"
"github.com/gorilla/schema" "github.com/gorilla/schema"
"github.com/gorilla/sessions" "github.com/gorilla/sessions"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
@ -24,13 +26,15 @@ import (
) )
// User represents the User API method handler set. // User represents the User API method handler set.
type User struct { type UserRepos struct {
UserRepo *user.Repository UserRepo handlers.UserRepository
AuthRepo *user_auth.Repository AuthRepo handlers.UserAuthRepository
UserAccountRepo *user_account.Repository UserAccountRepo handlers.UserAccountRepository
AccountRepo *account.Repository AccountRepo handlers.AccountRepository
GeoRepo GeoRepository
MasterDB *sqlx.DB MasterDB *sqlx.DB
Renderer web.Renderer Renderer web.Renderer
SecretKey string
} }
func urlUserVirtualLogin(userID string) string { func urlUserVirtualLogin(userID string) string {
@ -44,7 +48,7 @@ type UserLoginRequest struct {
} }
// Login handles authenticating a user into the system. // Login handles authenticating a user into the system.
func (h *User) Login(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h UserRepos) Login(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
ctxValues, err := webcontext.ContextValues(ctx) ctxValues, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {
@ -132,7 +136,7 @@ func (h *User) Login(ctx context.Context, w http.ResponseWriter, r *http.Request
} }
// Logout handles removing authentication for the user. // Logout handles removing authentication for the user.
func (h *User) Logout(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *UserRepos) Logout(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
sess := webcontext.ContextSession(ctx) sess := webcontext.ContextSession(ctx)
@ -148,7 +152,7 @@ func (h *User) Logout(ctx context.Context, w http.ResponseWriter, r *http.Reques
} }
// ResetPassword allows a user to perform forgot password. // ResetPassword allows a user to perform forgot password.
func (h *User) ResetPassword(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *UserRepos) ResetPassword(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
ctxValues, err := webcontext.ContextValues(ctx) ctxValues, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {
@ -208,7 +212,7 @@ func (h *User) ResetPassword(ctx context.Context, w http.ResponseWriter, r *http
} }
// ResetConfirm handles changing a users password after they have clicked on the link emailed. // ResetConfirm handles changing a users password after they have clicked on the link emailed.
func (h *User) ResetConfirm(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *UserRepos) ResetConfirm(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
resetHash := params["hash"] resetHash := params["hash"]
@ -278,7 +282,7 @@ func (h *User) ResetConfirm(ctx context.Context, w http.ResponseWriter, r *http.
return true, web.Redirect(ctx, w, r, "/", http.StatusFound) return true, web.Redirect(ctx, w, r, "/", http.StatusFound)
} }
_, err = h.UserRepo.ParseResetHash(ctx, resetHash, ctxValues.Now) _, err = user.ParseResetHash(ctx, h.SecretKey, resetHash, ctxValues.Now)
if err != nil { if err != nil {
switch errors.Cause(err) { switch errors.Cause(err) {
case user.ErrResetExpired: case user.ErrResetExpired:
@ -316,7 +320,7 @@ func (h *User) ResetConfirm(ctx context.Context, w http.ResponseWriter, r *http.
} }
// View handles displaying the current user profile. // View handles displaying the current user profile.
func (h *User) View(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *UserRepos) View(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
data := make(map[string]interface{}) data := make(map[string]interface{})
f := func() error { f := func() error {
@ -356,7 +360,7 @@ func (h *User) View(ctx context.Context, w http.ResponseWriter, r *http.Request,
} }
// Update handles allowing the current user to update their profile. // Update handles allowing the current user to update their profile.
func (h *User) Update(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *UserRepos) Update(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
ctxValues, err := webcontext.ContextValues(ctx) ctxValues, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {
@ -453,7 +457,7 @@ func (h *User) Update(ctx context.Context, w http.ResponseWriter, r *http.Reques
data["user"] = usr.Response(ctx) data["user"] = usr.Response(ctx)
data["timezones"], err = geonames.ListTimezones(ctx, h.MasterDB) data["timezones"], err = h.GeoRepo.ListTimezones(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -472,7 +476,7 @@ func (h *User) Update(ctx context.Context, w http.ResponseWriter, r *http.Reques
} }
// Account handles displaying the Account for the current user. // Account handles displaying the Account for the current user.
func (h *User) Account(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *UserRepos) Account(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
data := make(map[string]interface{}) data := make(map[string]interface{})
f := func() error { f := func() error {
@ -499,7 +503,7 @@ func (h *User) Account(ctx context.Context, w http.ResponseWriter, r *http.Reque
} }
// VirtualLogin handles switching the scope of the context to another user. // VirtualLogin handles switching the scope of the context to another user.
func (h *User) VirtualLogin(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *UserRepos) VirtualLogin(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
ctxValues, err := webcontext.ContextValues(ctx) ctxValues, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {
@ -634,7 +638,7 @@ func (h *User) VirtualLogin(ctx context.Context, w http.ResponseWriter, r *http.
} }
// VirtualLogout handles switching the scope back to the user who initiated the virtual login. // VirtualLogout handles switching the scope back to the user who initiated the virtual login.
func (h *User) VirtualLogout(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *UserRepos) VirtualLogout(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
ctxValues, err := webcontext.ContextValues(ctx) ctxValues, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {
@ -708,7 +712,7 @@ func (h *User) VirtualLogout(ctx context.Context, w http.ResponseWriter, r *http
} }
// VirtualLogin handles switching the scope of the context to another user. // VirtualLogin handles switching the scope of the context to another user.
func (h *User) SwitchAccount(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { func (h *UserRepos) SwitchAccount(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
ctxValues, err := webcontext.ContextValues(ctx) ctxValues, err := webcontext.ContextValues(ctx)
if err != nil { if err != nil {

View File

@ -3,11 +3,11 @@ package handlers
import ( import (
"context" "context"
"fmt" "fmt"
"geeks-accelerator/oss/saas-starter-kit/cmd/web-api/handlers"
"net/http" "net/http"
"strings" "strings"
"time" "time"
"geeks-accelerator/oss/saas-starter-kit/internal/geonames"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/datatable" "geeks-accelerator/oss/saas-starter-kit/internal/platform/datatable"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web"
@ -17,6 +17,7 @@ import (
"geeks-accelerator/oss/saas-starter-kit/internal/user_account" "geeks-accelerator/oss/saas-starter-kit/internal/user_account"
"geeks-accelerator/oss/saas-starter-kit/internal/user_account/invite" "geeks-accelerator/oss/saas-starter-kit/internal/user_account/invite"
"geeks-accelerator/oss/saas-starter-kit/internal/user_auth" "geeks-accelerator/oss/saas-starter-kit/internal/user_auth"
"github.com/dustin/go-humanize/english" "github.com/dustin/go-humanize/english"
"github.com/gorilla/schema" "github.com/gorilla/schema"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
@ -26,10 +27,12 @@ import (
// Users represents the Users API method handler set. // Users represents the Users API method handler set.
type Users struct { type Users struct {
UserRepo *user.Repository UserRepo handlers.UserRepository
UserAccountRepo *user_account.Repository AccountRepo handlers.AccountRepository
AuthRepo *user_auth.Repository UserAccountRepo handlers.UserAccountRepository
InviteRepo *invite.Repository AuthRepo handlers.UserAuthRepository
InviteRepo handlers.UserInviteRepository
GeoRepo GeoRepository
MasterDB *sqlx.DB MasterDB *sqlx.DB
Redis *redis.Client Redis *redis.Client
Renderer web.Renderer Renderer web.Renderer
@ -281,7 +284,7 @@ func (h *Users) Create(ctx context.Context, w http.ResponseWriter, r *http.Reque
return nil return nil
} }
data["timezones"], err = geonames.ListTimezones(ctx, h.MasterDB) data["timezones"], err = h.GeoRepo.ListTimezones(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -519,7 +522,7 @@ func (h *Users) Update(ctx context.Context, w http.ResponseWriter, r *http.Reque
data["user"] = usr.Response(ctx) data["user"] = usr.Response(ctx)
data["timezones"], err = geonames.ListTimezones(ctx, h.MasterDB) data["timezones"], err = h.GeoRepo.ListTimezones(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -798,7 +801,7 @@ func (h *Users) InviteAccept(ctx context.Context, w http.ResponseWriter, r *http
return nil return nil
} }
data["timezones"], err = geonames.ListTimezones(ctx, h.MasterDB) data["timezones"], err = h.GeoRepo.ListTimezones(ctx)
if err != nil { if err != nil {
return err return err
} }

View File

@ -7,6 +7,7 @@ import (
"expvar" "expvar"
"fmt" "fmt"
"geeks-accelerator/oss/saas-starter-kit/internal/account/account_preference" "geeks-accelerator/oss/saas-starter-kit/internal/account/account_preference"
"geeks-accelerator/oss/saas-starter-kit/internal/geonames"
"geeks-accelerator/oss/saas-starter-kit/internal/project" "geeks-accelerator/oss/saas-starter-kit/internal/project"
"geeks-accelerator/oss/saas-starter-kit/internal/signup" "geeks-accelerator/oss/saas-starter-kit/internal/signup"
"geeks-accelerator/oss/saas-starter-kit/internal/user_account" "geeks-accelerator/oss/saas-starter-kit/internal/user_account"
@ -40,6 +41,7 @@ import (
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"geeks-accelerator/oss/saas-starter-kit/internal/project_route" "geeks-accelerator/oss/saas-starter-kit/internal/project_route"
"geeks-accelerator/oss/saas-starter-kit/internal/user" "geeks-accelerator/oss/saas-starter-kit/internal/user"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/ec2metadata" "github.com/aws/aws-sdk-go/aws/ec2metadata"
@ -443,6 +445,7 @@ func main() {
usrRepo := user.NewRepository(masterDb, projectRoute.UserResetPassword, notifyEmail, cfg.Project.SharedSecretKey) usrRepo := user.NewRepository(masterDb, projectRoute.UserResetPassword, notifyEmail, cfg.Project.SharedSecretKey)
usrAccRepo := user_account.NewRepository(masterDb) usrAccRepo := user_account.NewRepository(masterDb)
accRepo := account.NewRepository(masterDb) accRepo := account.NewRepository(masterDb)
geoRepo := geonames.NewRepository(masterDb)
accPrefRepo := account_preference.NewRepository(masterDb) accPrefRepo := account_preference.NewRepository(masterDb)
authRepo := user_auth.NewRepository(masterDb, authenticator, usrRepo, usrAccRepo, accPrefRepo) authRepo := user_auth.NewRepository(masterDb, authenticator, usrRepo, usrAccRepo, accPrefRepo)
signupRepo := signup.NewRepository(masterDb, usrRepo, usrAccRepo, accRepo) signupRepo := signup.NewRepository(masterDb, usrRepo, usrAccRepo, accRepo)
@ -452,7 +455,7 @@ func main() {
appCtx := &handlers.AppContext{ appCtx := &handlers.AppContext{
Log: log, Log: log,
Env: cfg.Env, Env: cfg.Env,
MasterDB: masterDb, //MasterDB: masterDb,
Redis: redisClient, Redis: redisClient,
TemplateDir: cfg.Service.TemplateDir, TemplateDir: cfg.Service.TemplateDir,
StaticDir: cfg.Service.StaticFiles.Dir, StaticDir: cfg.Service.StaticFiles.Dir,
@ -462,6 +465,7 @@ func main() {
AccountRepo: accRepo, AccountRepo: accRepo,
AccountPrefRepo: accPrefRepo, AccountPrefRepo: accPrefRepo,
AuthRepo: authRepo, AuthRepo: authRepo,
GeoRepo: geoRepo,
SignupRepo: signupRepo, SignupRepo: signupRepo,
InviteRepo: inviteRepo, InviteRepo: inviteRepo,
ProjectRepo: prjRepo, ProjectRepo: prjRepo,

View File

@ -26,9 +26,9 @@ services:
redis: redis:
image: redis:latest image: redis:latest
expose: expose:
- "6379" - "6378"
ports: ports:
- "6379:6379" - "6378:6379"
networks: networks:
main: main:
aliases: aliases:

View File

@ -7,6 +7,7 @@ import (
"geeks-accelerator/oss/saas-starter-kit/internal/account" "geeks-accelerator/oss/saas-starter-kit/internal/account"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
"github.com/huandu/go-sqlbuilder" "github.com/huandu/go-sqlbuilder"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/pborman/uuid" "github.com/pborman/uuid"

View File

@ -2,8 +2,8 @@ package geonames
import ( import (
"context" "context"
"github.com/huandu/go-sqlbuilder" "github.com/huandu/go-sqlbuilder"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors" "github.com/pkg/errors"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
) )
@ -14,7 +14,7 @@ const (
) )
// FindCountries .... // FindCountries ....
func FindCountries(ctx context.Context, dbConn *sqlx.DB, orderBy, where string, args ...interface{}) ([]*Country, error) { func (repo *Repository) FindCountries(ctx context.Context, orderBy, where string, args ...interface{}) ([]*Country, error) {
span, ctx := tracer.StartSpanFromContext(ctx, "internal.geonames.FindCountries") span, ctx := tracer.StartSpanFromContext(ctx, "internal.geonames.FindCountries")
defer span.Finish() defer span.Finish()
@ -32,11 +32,11 @@ func FindCountries(ctx context.Context, dbConn *sqlx.DB, orderBy, where string,
} }
queryStr, queryArgs := query.Build() queryStr, queryArgs := query.Build()
queryStr = dbConn.Rebind(queryStr) queryStr = repo.DbConn.Rebind(queryStr)
args = append(args, queryArgs...) args = append(args, queryArgs...)
// fetch all places from the db // fetch all places from the db
rows, err := dbConn.QueryContext(ctx, queryStr, args...) rows, err := repo.DbConn.QueryContext(ctx, queryStr, args...)
if err != nil { if err != nil {
err = errors.Wrapf(err, "query - %s", query.String()) err = errors.Wrapf(err, "query - %s", query.String())
err = errors.WithMessage(err, "find countries failed") err = errors.WithMessage(err, "find countries failed")

View File

@ -2,8 +2,8 @@ package geonames
import ( import (
"context" "context"
"github.com/huandu/go-sqlbuilder" "github.com/huandu/go-sqlbuilder"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors" "github.com/pkg/errors"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
) )
@ -14,7 +14,7 @@ const (
) )
// FindCountryTimezones .... // FindCountryTimezones ....
func FindCountryTimezones(ctx context.Context, dbConn *sqlx.DB, orderBy, where string, args ...interface{}) ([]*CountryTimezone, error) { func (repo *Repository) FindCountryTimezones(ctx context.Context, orderBy, where string, args ...interface{}) ([]*CountryTimezone, error) {
span, ctx := tracer.StartSpanFromContext(ctx, "internal.geonames.FindCountryTimezones") span, ctx := tracer.StartSpanFromContext(ctx, "internal.geonames.FindCountryTimezones")
defer span.Finish() defer span.Finish()
@ -32,11 +32,11 @@ func FindCountryTimezones(ctx context.Context, dbConn *sqlx.DB, orderBy, where s
} }
queryStr, queryArgs := query.Build() queryStr, queryArgs := query.Build()
queryStr = dbConn.Rebind(queryStr) queryStr = repo.DbConn.Rebind(queryStr)
args = append(args, queryArgs...) args = append(args, queryArgs...)
// Fetch all country timezones from the db. // Fetch all country timezones from the db.
rows, err := dbConn.QueryContext(ctx, queryStr, args...) rows, err := repo.DbConn.QueryContext(ctx, queryStr, args...)
if err != nil { if err != nil {
err = errors.Wrapf(err, "query - %s", query.String()) err = errors.Wrapf(err, "query - %s", query.String())
err = errors.WithMessage(err, "find country timezones failed") err = errors.WithMessage(err, "find country timezones failed")
@ -64,8 +64,8 @@ func FindCountryTimezones(ctx context.Context, dbConn *sqlx.DB, orderBy, where s
return resp, nil return resp, nil
} }
func ListTimezones(ctx context.Context, dbConn *sqlx.DB) ([]string, error) { func (repo *Repository) ListTimezones(ctx context.Context) ([]string, error) {
res, err := FindCountryTimezones(ctx, dbConn, "timezone_id", "") res, err := repo.FindCountryTimezones(ctx, "timezone_id", "")
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -12,8 +12,9 @@ import (
"strings" "strings"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
"github.com/huandu/go-sqlbuilder" "github.com/huandu/go-sqlbuilder"
"github.com/jmoiron/sqlx" // "github.com/jmoiron/sqlx"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sethgrid/pester" "github.com/sethgrid/pester"
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
@ -43,7 +44,7 @@ func ValidGeonameCountries(ctx context.Context) []string {
} }
// FindGeonames .... // FindGeonames ....
func FindGeonames(ctx context.Context, dbConn *sqlx.DB, orderBy, where string, args ...interface{}) ([]*Geoname, error) { func (repo *Repository) FindGeonames(ctx context.Context, orderBy, where string, args ...interface{}) ([]*Geoname, error) {
span, ctx := tracer.StartSpanFromContext(ctx, "internal.geonames.FindGeonames") span, ctx := tracer.StartSpanFromContext(ctx, "internal.geonames.FindGeonames")
defer span.Finish() defer span.Finish()
@ -61,11 +62,11 @@ func FindGeonames(ctx context.Context, dbConn *sqlx.DB, orderBy, where string, a
} }
queryStr, queryArgs := query.Build() queryStr, queryArgs := query.Build()
queryStr = dbConn.Rebind(queryStr) queryStr = repo.DbConn.Rebind(queryStr)
args = append(args, queryArgs...) args = append(args, queryArgs...)
// fetch all places from the db // fetch all places from the db
rows, err := dbConn.QueryContext(ctx, queryStr, args...) rows, err := repo.DbConn.QueryContext(ctx, queryStr, args...)
if err != nil { if err != nil {
err = errors.Wrapf(err, "query - %s", query.String()) err = errors.Wrapf(err, "query - %s", query.String())
err = errors.WithMessage(err, "find regions failed") err = errors.WithMessage(err, "find regions failed")
@ -93,7 +94,7 @@ func FindGeonames(ctx context.Context, dbConn *sqlx.DB, orderBy, where string, a
} }
// FindGeonamePostalCodes .... // FindGeonamePostalCodes ....
func FindGeonamePostalCodes(ctx context.Context, dbConn *sqlx.DB, where string, args ...interface{}) ([]string, error) { func (repo *Repository) FindGeonamePostalCodes(ctx context.Context, where string, args ...interface{}) ([]string, error) {
span, ctx := tracer.StartSpanFromContext(ctx, "internal.geonames.FindGeonamePostalCodes") span, ctx := tracer.StartSpanFromContext(ctx, "internal.geonames.FindGeonamePostalCodes")
defer span.Finish() defer span.Finish()
@ -106,11 +107,11 @@ func FindGeonamePostalCodes(ctx context.Context, dbConn *sqlx.DB, where string,
} }
queryStr, queryArgs := query.Build() queryStr, queryArgs := query.Build()
queryStr = dbConn.Rebind(queryStr) queryStr = repo.DbConn.Rebind(queryStr)
args = append(args, queryArgs...) args = append(args, queryArgs...)
// fetch all places from the db // fetch all places from the db
rows, err := dbConn.QueryContext(ctx, queryStr, args...) rows, err := repo.DbConn.QueryContext(ctx, queryStr, args...)
if err != nil { if err != nil {
err = errors.Wrapf(err, "query - %s", query.String()) err = errors.Wrapf(err, "query - %s", query.String())
err = errors.WithMessage(err, "find regions failed") err = errors.WithMessage(err, "find regions failed")
@ -138,7 +139,7 @@ func FindGeonamePostalCodes(ctx context.Context, dbConn *sqlx.DB, where string,
} }
// FindGeonameRegions .... // FindGeonameRegions ....
func FindGeonameRegions(ctx context.Context, dbConn *sqlx.DB, orderBy, where string, args ...interface{}) ([]*Region, error) { func (repo *Repository) FindGeonameRegions(ctx context.Context, orderBy, where string, args ...interface{}) ([]*Region, error) {
span, ctx := tracer.StartSpanFromContext(ctx, "internal.geonames.FindGeonameRegions") span, ctx := tracer.StartSpanFromContext(ctx, "internal.geonames.FindGeonameRegions")
defer span.Finish() defer span.Finish()
@ -156,11 +157,11 @@ func FindGeonameRegions(ctx context.Context, dbConn *sqlx.DB, orderBy, where str
} }
queryStr, queryArgs := query.Build() queryStr, queryArgs := query.Build()
queryStr = dbConn.Rebind(queryStr) queryStr = repo.DbConn.Rebind(queryStr)
args = append(args, queryArgs...) args = append(args, queryArgs...)
// fetch all places from the db // fetch all places from the db
rows, err := dbConn.QueryContext(ctx, queryStr, args...) rows, err := repo.DbConn.QueryContext(ctx, queryStr, args...)
if err != nil { if err != nil {
err = errors.Wrapf(err, "query - %s", query.String()) err = errors.Wrapf(err, "query - %s", query.String())
err = errors.WithMessage(err, "find regions failed") err = errors.WithMessage(err, "find regions failed")
@ -194,7 +195,7 @@ func FindGeonameRegions(ctx context.Context, dbConn *sqlx.DB, orderBy, where str
// Possible types sent to the channel are limited to: // Possible types sent to the channel are limited to:
// - error // - error
// - GeoName // - GeoName
func LoadGeonames(ctx context.Context, rr chan<- interface{}, countries ...string) { func (repo *Repository) LoadGeonames(ctx context.Context, rr chan<- interface{}, countries ...string) {
defer close(rr) defer close(rr)
if len(countries) == 0 { if len(countries) == 0 {

View File

@ -1,6 +1,18 @@
package geonames package geonames
import "github.com/shopspring/decimal" import "github.com/shopspring/decimal"
import "github.com/jmoiron/sqlx"
type Repository struct {
DbConn *sqlx.DB
}
// NewRepository creates a new Repository that defines dependencies for Project.
func NewRepository(db *sqlx.DB) *Repository {
return &Repository{
DbConn: db,
}
}
type Geoname struct { type Geoname struct {
CountryCode string // US CountryCode string // US

View File

@ -9,6 +9,7 @@ import (
"strings" "strings"
"geeks-accelerator/oss/saas-starter-kit/internal/geonames" "geeks-accelerator/oss/saas-starter-kit/internal/geonames"
"github.com/geeks-accelerator/sqlxmigrate" "github.com/geeks-accelerator/sqlxmigrate"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
_ "github.com/lib/pq" _ "github.com/lib/pq"
@ -19,6 +20,7 @@ import (
// migrationList returns a list of migrations to be executed. If the id of the // migrationList returns a list of migrations to be executed. If the id of the
// migration already exists in the migrations table it will be skipped. // migration already exists in the migrations table it will be skipped.
func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest bool) []*sqlxmigrate.Migration { func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest bool) []*sqlxmigrate.Migration {
geoRepo := geonames.NewRepository(db)
return []*sqlxmigrate.Migration{ return []*sqlxmigrate.Migration{
// Create table users. // Create table users.
{ {
@ -253,7 +255,7 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest
} else { } else {
resChan := make(chan interface{}) resChan := make(chan interface{})
go geonames.LoadGeonames(ctx, resChan) go geoRepo.LoadGeonames(ctx, resChan)
for r := range resChan { for r := range resChan {
switch v := r.(type) { switch v := r.(type) {

View File

@ -6,11 +6,12 @@ import (
"strings" "strings"
"time" "time"
"geeks-accelerator/oss/saas-starter-kit/internal/account" //"geeks-accelerator/oss/saas-starter-kit/internal/account"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
"geeks-accelerator/oss/saas-starter-kit/internal/user" "geeks-accelerator/oss/saas-starter-kit/internal/user"
"geeks-accelerator/oss/saas-starter-kit/internal/user_account" "geeks-accelerator/oss/saas-starter-kit/internal/user_account"
"github.com/pkg/errors" "github.com/pkg/errors"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
) )
@ -40,7 +41,7 @@ func (repo *Repository) SendUserInvites(ctx context.Context, claims auth.Claims,
} }
// Ensure the claims can modify the account specified in the request. // Ensure the claims can modify the account specified in the request.
err = account.CanModifyAccount(ctx, claims, repo.DbConn, req.AccountID) err = repo.Account.CanModifyAccount(ctx, claims, req.AccountID)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -11,6 +11,7 @@ import (
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
"geeks-accelerator/oss/saas-starter-kit/internal/user" "geeks-accelerator/oss/saas-starter-kit/internal/user"
"geeks-accelerator/oss/saas-starter-kit/internal/user_account" "geeks-accelerator/oss/saas-starter-kit/internal/user_account"
"github.com/huandu/go-sqlbuilder" "github.com/huandu/go-sqlbuilder"
"github.com/lib/pq" "github.com/lib/pq"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -100,7 +101,8 @@ func (repo *Repository) SwitchAccount(ctx context.Context, claims auth.Claims, r
} }
// VirtualLogin allows users to mock being logged in as other users. // VirtualLogin allows users to mock being logged in as other users.
func (repo *Repository) VirtualLogin(ctx context.Context, claims auth.Claims, req VirtualLoginRequest, expires time.Duration, now time.Time, scopes ...string) (Token, error) { func (repo *Repository) VirtualLogin(ctx context.Context, claims auth.Claims, req VirtualLoginRequest,
expires time.Duration, now time.Time, scopes ...string) (Token, error) {
span, ctx := tracer.StartSpanFromContext(ctx, "internal.user_auth.VirtualLogin") span, ctx := tracer.StartSpanFromContext(ctx, "internal.user_auth.VirtualLogin")
defer span.Finish() defer span.Finish()