Esempio n. 1
0
// NewService creates a new store Service which handles websites, groups and stores.
// A Service can only act on a certain scope (MAGE_RUN_TYPE) and scope ID (MAGE_RUN_CODE).
// Default scope.Scope is always the scope.WebsiteID constant.
// This function is mainly used when booting the app to set the environment configuration
// Also all other calls to any method receiver with nil arguments depends on the internal
// appStore which reflects the default store ID.
func NewService(so scope.Option, storage Storager, opts ...ServiceOption) (*Service, error) {
	scopeID := so.Scope()
	if scopeID == scope.DefaultID {
		scopeID = scope.WebsiteID
	}

	s := &Service{
		cr:           config.DefaultManager,
		boundToScope: scopeID,
		storage:      storage,
		mu:           sync.RWMutex{},
		websiteMap:   make(map[uint64]*Website),
		groupMap:     make(map[uint64]*Group),
		storeMap:     make(map[uint64]*Store),
	}
	for _, opt := range opts {
		if opt != nil {
			opt(s)
		}
	}

	var err error
	s.appStore, err = s.findDefaultStoreByScope(s.boundToScope, so)
	if err != nil {
		if PkgLog.IsDebug() {
			PkgLog.Debug("store.Service.Init", "err", err, "ScopeOption", so)
		}
		return nil, errgo.Mask(err)
	}

	return s, nil
}
Esempio n. 2
0
func TestApplyStore(t *testing.T) {
	so := scope.Option{Store: scope.MockID(3)}
	assert.NotNil(t, so)
	assert.Equal(t, int64(3), so.Store.StoreID())
	assert.Nil(t, so.Website)
	assert.Nil(t, so.Group)
	assert.Exactly(t, scope.StoreID.String(), so.String())
}
Esempio n. 3
0
// RequestedStore see interface description Reader.RequestedStore
func (sm *Service) RequestedStore(so scope.Option) (activeStore *Store, err error) {

	activeStore, err = sm.findDefaultStoreByScope(so.Scope(), so)
	if err != nil {
		if PkgLog.IsDebug() {
			PkgLog.Debug("store.Service.RequestedStore.FindDefaultStoreByScope", "err", err, "so", so)
		}
		return nil, err
	}

	//	activeStore, err = sm.newActiveStore(activeStore) // this is the active store from a request.
	// todo rethink here if we really need a newActiveStore
	// newActiveStore creates a new Store, Website and Group pointers !!!
	//	if activeStore == nil || err != nil {
	//		// store is not active so ignore
	//		return nil, err
	//	}

	if false == activeStore.Data.IsActive {
		return nil, ErrStoreNotActive
	}

	allowStoreChange := false
	switch sm.boundToScope {
	case scope.StoreID:
		allowStoreChange = true
		break
	case scope.GroupID:
		allowStoreChange = activeStore.Data.GroupID == sm.appStore.Data.GroupID
		break
	case scope.WebsiteID:
		allowStoreChange = activeStore.Data.WebsiteID == sm.appStore.Data.WebsiteID
		break
	}

	if allowStoreChange {
		return activeStore, nil
	}
	return nil, ErrStoreChangeNotAllowed
}
Esempio n. 4
0
func testStoreCodeFrom(t *testing.T, i int, haveErr, wantErr error, haveScope scope.Option, wantScope scope.Scope, wantCode string, wantID int64) {
	if wantErr != nil {
		assert.EqualError(t, haveErr, wantErr.Error(), "Index: %d", i)

	}
	switch sos := haveScope.Scope(); sos {
	case scope.StoreID:
		assert.Exactly(t, wantID, haveScope.Store.StoreID(), "Index: %d", i)
	case scope.GroupID:
		assert.Exactly(t, wantID, haveScope.Group.GroupID(), "Index: %d", i)
	case scope.WebsiteID:
		assert.Exactly(t, wantID, haveScope.Website.WebsiteID(), "Index: %d", i)
	case scope.DefaultID:
		assert.Nil(t, haveScope.Store, "Index: %d", i)
		assert.Nil(t, haveScope.Group, "Index: %d", i)
		assert.Nil(t, haveScope.Website, "Index: %d", i)
	default:
		t.Fatalf("Unknown scope: %d", sos)
	}
	assert.Exactly(t, wantScope, haveScope.Scope(), "Index: %d", i)
	assert.Exactly(t, wantCode, haveScope.StoreCode(), "Index: %d", i)
}
Esempio n. 5
0
// WithInitStoreByFormCookie reads from a GET parameter or cookie the store code.
// Checks if the store code is valid and allowed. If so it adjusts the context.Context
// to provide the new requestedStore.
//
// It calls Reader.RequestedStore() to determine the correct store.
// 		1. check cookie store, always a string and the store code
// 		2. check for GET ___store variable, always a string and the store code
func WithInitStoreByFormCookie() ctxhttp.Middleware {
	return func(h ctxhttp.Handler) ctxhttp.Handler {
		return ctxhttp.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {

			storeService, requestedStore, err := FromContextReader(ctx)
			if err != nil {
				if PkgLog.IsDebug() {
					PkgLog.Debug("store.WithInitStoreByToken.FromContextServiceReader", "err", err, "ctx", ctx)
				}
				return errgo.Mask(err)
			}

			var reqSO scope.Option

			reqSO, err = CodeFromRequestGET(r)
			if err != nil {
				if PkgLog.IsDebug() {
					PkgLog.Debug("store.WithInitStoreByFormCookie.StoreCodeFromRequestGET", "err", err, "req", r, "scope", reqSO)
				}

				reqSO, err = CodeFromCookie(r)
				if err != nil {
					// ignore further processing because all codes are invalid or not found
					if PkgLog.IsDebug() {
						PkgLog.Debug("store.WithInitStoreByFormCookie.StoreCodeFromCookie", "err", err, "req", r, "scope", reqSO)
					}
					return h.ServeHTTPContext(ctx, w, r)
				}
			}

			var newRequestedStore *Store
			if newRequestedStore, err = storeService.RequestedStore(reqSO); err != nil {
				if PkgLog.IsDebug() {
					PkgLog.Debug("store.WithInitStoreByFormCookie.storeService.RequestedStore", "err", err, "req", r, "scope", reqSO)
				}
				return errgo.Mask(err)
			}

			soStoreCode := reqSO.StoreCode()

			// delete and re-set a new cookie, adjust context.Context
			if newRequestedStore != nil && newRequestedStore.Data.Code.String == soStoreCode {
				wds, err := newRequestedStore.Website.DefaultStore()
				if err != nil {
					if PkgLog.IsDebug() {
						PkgLog.Debug("store.WithInitStoreByFormCookie.Website.DefaultStore", "err", err, "soStoreCode", soStoreCode)
					}
					return errgo.Mask(err)
				}
				if wds.Data.Code.String == soStoreCode {
					newRequestedStore.DeleteCookie(w) // cookie not needed anymore
				} else {
					newRequestedStore.SetCookie(w) // make sure we force set the new store

					if newRequestedStore.StoreID() != requestedStore.StoreID() {
						// this may lead to a bug because the previously set storeService and requestedStore
						// will still exists and have not been removed.
						ctx = NewContextReader(ctx, storeService, newRequestedStore)
					}
				}
			}

			return h.ServeHTTPContext(ctx, w, r)

		})
	}
}
Esempio n. 6
0
func TestApplyDefault(t *testing.T) {
	so := scope.Option{}
	assert.NotNil(t, so)
	assert.Exactly(t, scope.DefaultID, so.Scope())
}