1
0
mirror of https://github.com/raseels-repos/golang-saas-starter-kit.git synced 2024-11-24 08:42:20 +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"
"net/http"
"strconv"
"time"
"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/web"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"github.com/pkg/errors"
"gopkg.in/go-playground/validator.v9"
)
// Account represents the Account API method handler set.
type Account struct {
*account.Repository
type Accounts struct {
Repository AccountRepository
// 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
// @Summary Get account by ID
// @Description Read returns the specified account from the system.
@ -34,7 +56,7 @@ type Account struct {
// @Failure 404 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse
// @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)
if !ok {
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 500 {object} weberror.ErrorResponse
// @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)
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/weberror"
"geeks-accelerator/oss/saas-starter-kit/internal/project"
"github.com/pkg/errors"
"net/http"
"github.com/pkg/errors"
)
// Example represents the Example API method handler set.
type Example struct {
Project *project.Repository
Project ProjectRepository
// ADD OTHER STATE LIKE THE LOGGER AND CONFIG HERE.
}

View File

@ -5,23 +5,35 @@ import (
"net/http"
"strconv"
"strings"
"time"
"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/webcontext"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
"geeks-accelerator/oss/saas-starter-kit/internal/project"
"github.com/pkg/errors"
"gopkg.in/go-playground/validator.v9"
)
// Project represents the Project API method handler set.
type Project struct {
*project.Repository
type Projects struct {
Repository ProjectRepository
// 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
// TODO: Need to implement unittests on projects/find endpoint. There are none.
// @Summary List projects
@ -40,7 +52,7 @@ type Project struct {
// @Failure 403 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse
// @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)
if !ok {
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 500 {object} weberror.ErrorResponse
// @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)
if !ok {
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 500 {object} weberror.ErrorResponse
// @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)
if err != nil {
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 500 {object} weberror.ErrorResponse
// @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)
if err != nil {
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 500 {object} weberror.ErrorResponse
// @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)
if err != nil {
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 500 {object} weberror.ErrorResponse
// @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)
if err != nil {
return err

View File

@ -5,21 +5,14 @@ import (
"net/http"
"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"
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/web"
"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/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"
"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"
"gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis"
)
@ -29,14 +22,14 @@ type AppContext struct {
Env webcontext.Env
MasterDB *sqlx.DB
Redis *redis.Client
UserRepo *user.Repository
UserAccountRepo *user_account.Repository
AccountRepo *account.Repository
AccountPrefRepo *account_preference.Repository
AuthRepo *user_auth.Repository
SignupRepo *signup.Repository
InviteRepo *invite.Repository
ProjectRepo *project.Repository
UserRepo UserRepository
UserAccountRepo UserAccountRepository
AccountRepo AccountRepository
AccountPrefRepo AccountPrefRepository
AuthRepo UserAuthRepository
SignupRepo SignupRepository
InviteRepo UserInviteRepository
ProjectRepo ProjectRepository
Authenticator *auth.Authenticator
PreAppMiddleware []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)
// Register user management and authentication endpoints.
u := User{
Repository: appCtx.UserRepo,
Auth: appCtx.AuthRepo,
u := Users{
UserRepo: appCtx.UserRepo,
AuthRepo: appCtx.AuthRepo,
}
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))
@ -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))
// Register account endpoints.
a := Account{
a := Accounts{
Repository: appCtx.AccountRepo,
}
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)
// Register project.
p := Project{
p := Projects{
Repository: appCtx.ProjectRepo,
}
app.Handle("GET", "/v1/projects", p.Find, mid.AuthenticateHeader(appCtx.Authenticator))

View File

@ -3,6 +3,7 @@ package handlers
import (
"context"
"net/http"
"time"
"geeks-accelerator/oss/saas-starter-kit/internal/account"
"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/weberror"
"geeks-accelerator/oss/saas-starter-kit/internal/signup"
"github.com/pkg/errors"
"gopkg.in/go-playground/validator.v9"
)
// Signup represents the Signup API method handler set.
type Signup struct {
*signup.Repository
Repository SignupRepository
// 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
// @Summary Signup handles new account creation.
// @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/user"
"geeks-accelerator/oss/saas-starter-kit/internal/user_auth"
"github.com/gorilla/schema"
"github.com/pkg/errors"
"gopkg.in/go-playground/validator.v9"
@ -22,13 +23,36 @@ import (
var sessionTtl = time.Hour * 24
// User represents the User API method handler set.
type User struct {
*user.Repository
Auth *user_auth.Repository
type Users struct {
AuthRepo UserAuthRepository
UserRepo UserRepository
// 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
// TODO: Need to implement unittests on users/find endpoint. There are none.
// @Summary List users
@ -46,7 +70,7 @@ type User struct {
// @Failure 400 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse
// @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)
if !ok {
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)
//}
res, err := h.Repository.Find(ctx, claims, req)
res, err := h.UserRepo.Find(ctx, claims, req)
if err != nil {
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 500 {object} weberror.ErrorResponse
// @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)
if !ok {
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
}
res, err := h.Repository.Read(ctx, claims, user.UserReadRequest{
res, err := h.UserRepo.Read(ctx, claims, user.UserReadRequest{
ID: params["id"],
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 500 {object} weberror.ErrorResponse
// @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)
if err != nil {
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)
}
res, err := h.Repository.Create(ctx, claims, req, v.Now)
usr, err := h.UserRepo.Create(ctx, claims, req, v.Now)
if err != nil {
cause := errors.Cause(err)
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
@ -237,7 +261,7 @@ func (h *User) Create(ctx context.Context, w http.ResponseWriter, r *http.Reques
// @Failure 403 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse
// @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)
if err != nil {
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)
}
err = h.Repository.Update(ctx, claims, req, v.Now)
err = h.UserRepo.Update(ctx, claims, req, v.Now)
if err != nil {
cause := errors.Cause(err)
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 500 {object} weberror.ErrorResponse
// @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)
if err != nil {
return err
@ -307,7 +331,7 @@ func (h *User) UpdatePassword(ctx context.Context, w http.ResponseWriter, r *htt
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 {
cause := errors.Cause(err)
switch cause {
@ -341,7 +365,7 @@ func (h *User) UpdatePassword(ctx context.Context, w http.ResponseWriter, r *htt
// @Failure 403 {object} weberror.ErrorResponse
// @Failure 500 {object} weberror.ErrorResponse
// @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)
if err != nil {
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)
}
err = h.Repository.Archive(ctx, claims, req, v.Now)
err = h.UserRepo.Archive(ctx, claims, req, v.Now)
if err != nil {
cause := errors.Cause(err)
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 500 {object} weberror.ErrorResponse
// @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)
if err != nil {
return err
}
err = h.Repository.Delete(ctx, claims,
err = h.UserRepo.Delete(ctx, claims,
user.UserDeleteRequest{ID: params["id"]})
if err != nil {
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 500 {object} weberror.ErrorResponse
// @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)
if err != nil {
return err
@ -442,7 +466,7 @@ func (h *User) SwitchAccount(ctx context.Context, w http.ResponseWriter, r *http
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"],
}, sessionTtl, v.Now)
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 500 {object} weberror.ErrorResponse
// @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)
if err != nil {
return err
@ -533,7 +557,7 @@ func (h *User) Token(ctx context.Context, w http.ResponseWriter, r *http.Request
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 {
cause := errors.Cause(err)
switch cause {

View File

@ -5,23 +5,44 @@ import (
"net/http"
"strconv"
"strings"
"time"
"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/webcontext"
"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/invite"
"github.com/pkg/errors"
"gopkg.in/go-playground/validator.v9"
)
// UserAccount represents the UserAccount API method handler set.
type UserAccount struct {
*user_account.Repository
UserInvite UserInviteRepository
Repository UserAccountRepository
// 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
// TODO: Need to implement unittests on user_accounts/find endpoint. There are none.
// @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/invite"
"geeks-accelerator/oss/saas-starter-kit/internal/user_auth"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"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)
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)

View File

@ -13,6 +13,7 @@ import (
"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/weberror"
"github.com/pborman/uuid"
)

View File

@ -2,9 +2,7 @@ package handlers
import (
"context"
"net/http"
"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/account_preference"
"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/webcontext"
"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/jmoiron/sqlx"
"github.com/pkg/errors"
)
// Account represents the Account API method handler set.
type Account struct {
AccountRepo *account.Repository
AccountPrefRepo *account_preference.Repository
AuthRepo *user_auth.Repository
AccountRepo handlers.AccountRepository
AccountPrefRepo handlers.AccountPrefRepository
AuthRepo handlers.UserAuthRepository
GeoRepo GeoRepository
Authenticator *auth.Authenticator
MasterDB *sqlx.DB
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["timezones"], err = geonames.ListTimezones(ctx, h.MasterDB)
data["timezones"], err = h.GeoRepo.ListTimezones(ctx)
if err != nil {
return false, err
}
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 {
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/platform/web"
"github.com/jmoiron/sqlx"
//"github.com/jmoiron/sqlx"
"gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis"
)
// Check provides support for orchestration geo endpoints.
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...
@ -39,7 +50,7 @@ func (h *Geo) GeonameByPostalCode(ctx context.Context, w http.ResponseWriter, r
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 {
fmt.Printf("%+v", 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 ")
res, err := geonames.FindGeonamePostalCodes(ctx, h.MasterDB, where, args...)
res, err := h.GeoRepo.FindGeonamePostalCodes(ctx, where, args...)
if err != nil {
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 ")
res, err := geonames.FindGeonameRegions(ctx, h.MasterDB, "state_name", where, args...)
res, err := h.GeoRepo.FindGeonameRegions(ctx, "state_name", where, args...)
if err != nil {
fmt.Printf("%+v", 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 ")
res, err := geonames.FindCountryTimezones(ctx, h.MasterDB, "timezone_id", where, args...)
res, err := h.GeoRepo.FindCountryTimezones(ctx, "timezone_id", where, args...)
if err != nil {
return web.RespondJsonError(ctx, w, err)
}

View File

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

View File

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

View File

@ -2,6 +2,7 @@ package handlers
import (
"context"
"geeks-accelerator/oss/saas-starter-kit/cmd/web-api/handlers"
"net/http"
"time"
@ -13,6 +14,7 @@ import (
"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/user_auth"
"github.com/gorilla/schema"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
@ -20,8 +22,9 @@ import (
// Signup represents the Signup API method handler set.
type Signup struct {
SignupRepo *signup.Repository
AuthRepo *user_auth.Repository
SignupRepo handlers.SignupRepository
AuthRepo handlers.UserAuthRepository
GeoRepo GeoRepository
MasterDB *sqlx.DB
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["countries"], err = geonames.FindCountries(ctx, h.MasterDB, "name", "")
data["countries"], err = h.GeoRepo.FindCountries(ctx, "name", "")
if err != nil {
return err
}

View File

@ -8,8 +8,9 @@ import (
"strings"
"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/geonames"
"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/webcontext"
@ -17,6 +18,7 @@ import (
"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_auth"
"github.com/gorilla/schema"
"github.com/gorilla/sessions"
"github.com/jmoiron/sqlx"
@ -24,13 +26,15 @@ import (
)
// User represents the User API method handler set.
type User struct {
UserRepo *user.Repository
AuthRepo *user_auth.Repository
UserAccountRepo *user_account.Repository
AccountRepo *account.Repository
type UserRepos struct {
UserRepo handlers.UserRepository
AuthRepo handlers.UserAuthRepository
UserAccountRepo handlers.UserAccountRepository
AccountRepo handlers.AccountRepository
GeoRepo GeoRepository
MasterDB *sqlx.DB
Renderer web.Renderer
SecretKey string
}
func urlUserVirtualLogin(userID string) string {
@ -44,7 +48,7 @@ type UserLoginRequest struct {
}
// 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)
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.
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)
@ -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.
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)
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.
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"]
@ -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)
}
_, err = h.UserRepo.ParseResetHash(ctx, resetHash, ctxValues.Now)
_, err = user.ParseResetHash(ctx, h.SecretKey, resetHash, ctxValues.Now)
if err != nil {
switch errors.Cause(err) {
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.
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{})
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.
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)
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["timezones"], err = geonames.ListTimezones(ctx, h.MasterDB)
data["timezones"], err = h.GeoRepo.ListTimezones(ctx)
if err != nil {
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.
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{})
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.
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)
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.
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)
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.
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)
if err != nil {

View File

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

View File

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

View File

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

View File

@ -7,6 +7,7 @@ import (
"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/web/webcontext"
"github.com/huandu/go-sqlbuilder"
"github.com/jmoiron/sqlx"
"github.com/pborman/uuid"

View File

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

View File

@ -2,8 +2,8 @@ package geonames
import (
"context"
"github.com/huandu/go-sqlbuilder"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)
@ -14,7 +14,7 @@ const (
)
// 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")
defer span.Finish()
@ -32,11 +32,11 @@ func FindCountryTimezones(ctx context.Context, dbConn *sqlx.DB, orderBy, where s
}
queryStr, queryArgs := query.Build()
queryStr = dbConn.Rebind(queryStr)
queryStr = repo.DbConn.Rebind(queryStr)
args = append(args, queryArgs...)
// 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 {
err = errors.Wrapf(err, "query - %s", query.String())
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
}
func ListTimezones(ctx context.Context, dbConn *sqlx.DB) ([]string, error) {
res, err := FindCountryTimezones(ctx, dbConn, "timezone_id", "")
func (repo *Repository) ListTimezones(ctx context.Context) ([]string, error) {
res, err := repo.FindCountryTimezones(ctx, "timezone_id", "")
if err != nil {
return nil, err
}

View File

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

View File

@ -1,6 +1,18 @@
package geonames
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 {
CountryCode string // US

View File

@ -9,6 +9,7 @@ import (
"strings"
"geeks-accelerator/oss/saas-starter-kit/internal/geonames"
"github.com/geeks-accelerator/sqlxmigrate"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
@ -19,6 +20,7 @@ import (
// 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.
func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest bool) []*sqlxmigrate.Migration {
geoRepo := geonames.NewRepository(db)
return []*sqlxmigrate.Migration{
// Create table users.
{
@ -253,7 +255,7 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest
} else {
resChan := make(chan interface{})
go geonames.LoadGeonames(ctx, resChan)
go geoRepo.LoadGeonames(ctx, resChan)
for r := range resChan {
switch v := r.(type) {

View File

@ -6,11 +6,12 @@ import (
"strings"
"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/web/webcontext"
"geeks-accelerator/oss/saas-starter-kit/internal/user"
"geeks-accelerator/oss/saas-starter-kit/internal/user_account"
"github.com/pkg/errors"
"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.
err = account.CanModifyAccount(ctx, claims, repo.DbConn, req.AccountID)
err = repo.Account.CanModifyAccount(ctx, claims, req.AccountID)
if err != nil {
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/user"
"geeks-accelerator/oss/saas-starter-kit/internal/user_account"
"github.com/huandu/go-sqlbuilder"
"github.com/lib/pq"
"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.
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")
defer span.Finish()