1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-04-24 13:48:49 +08:00
b1ackd0t 23a665b54a
MF-1510 - Add Event Sourcing To Users Service (#1835)
* Add Event Sourcing on Users Service

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Modify Events Sourced From Things Service

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Rename Cache

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Remove SharedBy From Events

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Use Combined Publisher

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Format Docker Compose File

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Rename Events

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
2023-08-02 12:09:56 +02:00

295 lines
6.6 KiB
Go

// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0
package redis
import (
"context"
"github.com/go-redis/redis/v8"
mfredis "github.com/mainflux/mainflux/internal/clients/redis"
mfclients "github.com/mainflux/mainflux/pkg/clients"
"github.com/mainflux/mainflux/users/clients"
"github.com/mainflux/mainflux/users/jwt"
)
const (
streamID = "mainflux.users"
streamLen = 1000
)
var _ clients.Service = (*eventStore)(nil)
type eventStore struct {
mfredis.Publisher
svc clients.Service
client *redis.Client
}
// NewEventStoreMiddleware returns wrapper around users service that sends
// events to event store.
func NewEventStoreMiddleware(ctx context.Context, svc clients.Service, client *redis.Client) clients.Service {
es := eventStore{
svc: svc,
client: client,
Publisher: mfredis.NewEventStore(client, streamID, streamLen),
}
go es.StartPublishingRoutine(ctx)
return es
}
func (es eventStore) RegisterClient(ctx context.Context, token string, user mfclients.Client) (mfclients.Client, error) {
user, err := es.svc.RegisterClient(ctx, token, user)
if err != nil {
return user, err
}
event := createClientEvent{
user,
}
if err := es.Publish(ctx, event); err != nil {
return user, err
}
return user, nil
}
func (es eventStore) UpdateClient(ctx context.Context, token string, user mfclients.Client) (mfclients.Client, error) {
user, err := es.svc.UpdateClient(ctx, token, user)
if err != nil {
return user, err
}
return es.update(ctx, "", user)
}
func (es eventStore) UpdateClientOwner(ctx context.Context, token string, user mfclients.Client) (mfclients.Client, error) {
user, err := es.svc.UpdateClientOwner(ctx, token, user)
if err != nil {
return user, err
}
return es.update(ctx, "owner", user)
}
func (es eventStore) UpdateClientTags(ctx context.Context, token string, user mfclients.Client) (mfclients.Client, error) {
user, err := es.svc.UpdateClientTags(ctx, token, user)
if err != nil {
return user, err
}
return es.update(ctx, "tags", user)
}
func (es eventStore) UpdateClientSecret(ctx context.Context, token, oldSecret, newSecret string) (mfclients.Client, error) {
user, err := es.svc.UpdateClientSecret(ctx, token, oldSecret, newSecret)
if err != nil {
return user, err
}
return es.update(ctx, "secret", user)
}
func (es eventStore) UpdateClientIdentity(ctx context.Context, token, id, identity string) (mfclients.Client, error) {
user, err := es.svc.UpdateClientIdentity(ctx, token, id, identity)
if err != nil {
return user, err
}
return es.update(ctx, "identity", user)
}
func (es eventStore) update(ctx context.Context, operation string, user mfclients.Client) (mfclients.Client, error) {
event := updateClientEvent{
user, operation,
}
if err := es.Publish(ctx, event); err != nil {
return user, err
}
return user, nil
}
func (es eventStore) ViewClient(ctx context.Context, token, id string) (mfclients.Client, error) {
user, err := es.svc.ViewClient(ctx, token, id)
if err != nil {
return user, err
}
event := viewClientEvent{
user,
}
if err := es.Publish(ctx, event); err != nil {
return user, err
}
return user, nil
}
func (es eventStore) ViewProfile(ctx context.Context, token string) (mfclients.Client, error) {
user, err := es.svc.ViewProfile(ctx, token)
if err != nil {
return user, err
}
event := viewProfileEvent{
user,
}
if err := es.Publish(ctx, event); err != nil {
return user, err
}
return user, nil
}
func (es eventStore) ListClients(ctx context.Context, token string, pm mfclients.Page) (mfclients.ClientsPage, error) {
cp, err := es.svc.ListClients(ctx, token, pm)
if err != nil {
return cp, err
}
event := listClientEvent{
pm,
}
if err := es.Publish(ctx, event); err != nil {
return cp, err
}
return cp, nil
}
func (es eventStore) ListMembers(ctx context.Context, token, groupID string, pm mfclients.Page) (mfclients.MembersPage, error) {
mp, err := es.svc.ListMembers(ctx, token, groupID, pm)
if err != nil {
return mp, err
}
event := listClientByGroupEvent{
pm, groupID,
}
if err := es.Publish(ctx, event); err != nil {
return mp, err
}
return mp, nil
}
func (es eventStore) EnableClient(ctx context.Context, token, id string) (mfclients.Client, error) {
user, err := es.svc.EnableClient(ctx, token, id)
if err != nil {
return user, err
}
return es.delete(ctx, user)
}
func (es eventStore) DisableClient(ctx context.Context, token, id string) (mfclients.Client, error) {
user, err := es.svc.DisableClient(ctx, token, id)
if err != nil {
return user, err
}
return es.delete(ctx, user)
}
func (es eventStore) delete(ctx context.Context, user mfclients.Client) (mfclients.Client, error) {
event := removeClientEvent{
id: user.ID,
updatedAt: user.UpdatedAt,
updatedBy: user.UpdatedBy,
status: user.Status.String(),
}
if err := es.Publish(ctx, event); err != nil {
return user, err
}
return user, nil
}
func (es eventStore) Identify(ctx context.Context, token string) (string, error) {
userID, err := es.svc.Identify(ctx, token)
if err != nil {
return userID, err
}
event := identifyClientEvent{
userID: userID,
}
if err := es.Publish(ctx, event); err != nil {
return userID, err
}
return userID, nil
}
func (es eventStore) GenerateResetToken(ctx context.Context, email, host string) error {
if err := es.svc.GenerateResetToken(ctx, email, host); err != nil {
return err
}
event := generateResetTokenEvent{
email: email,
host: host,
}
return es.Publish(ctx, event)
}
func (es eventStore) IssueToken(ctx context.Context, identity, secret string) (jwt.Token, error) {
token, err := es.svc.IssueToken(ctx, identity, secret)
if err != nil {
return token, err
}
event := issueTokenEvent{
identity: identity,
}
if err := es.Publish(ctx, event); err != nil {
return token, err
}
return token, nil
}
func (es eventStore) RefreshToken(ctx context.Context, refreshToken string) (jwt.Token, error) {
token, err := es.svc.RefreshToken(ctx, refreshToken)
if err != nil {
return token, err
}
event := refreshTokenEvent{}
if err := es.Publish(ctx, event); err != nil {
return token, err
}
return token, nil
}
func (es eventStore) ResetSecret(ctx context.Context, resetToken, secret string) error {
if err := es.svc.ResetSecret(ctx, resetToken, secret); err != nil {
return err
}
event := resetSecretEvent{}
return es.Publish(ctx, event)
}
func (es eventStore) SendPasswordReset(ctx context.Context, host, email, user, token string) error {
if err := es.svc.SendPasswordReset(ctx, host, email, user, token); err != nil {
return err
}
event := sendPasswordResetEvent{
host: host,
email: email,
user: user,
}
return es.Publish(ctx, event)
}