Skip to content

Commit

Permalink
Merge pull request #1194 from mattwoberts/userlist
Browse files Browse the repository at this point in the history
Userlist Integration
  • Loading branch information
mattwoberts authored Sep 12, 2024
2 parents 1c1220b + ebae321 commit 142232d
Show file tree
Hide file tree
Showing 19 changed files with 732 additions and 4 deletions.
5 changes: 4 additions & 1 deletion .test.env
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,7 @@ EMAIL_SMTP_USERNAME=us3r
EMAIL_SMTP_PASSWORD=p4ss

EMAIL_MAILGUN_API=mys3cr3tk3y
EMAIL_MAILGUN_DOMAIN=mydomain.com
EMAIL_MAILGUN_DOMAIN=mydomain.com

USER_LIST_ENABLED=true
USER_LIST_APIKEY=abcdefg
5 changes: 3 additions & 2 deletions app/cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ import (
_ "github.com/getfider/fider/app/services/log/sql"
_ "github.com/getfider/fider/app/services/oauth"
_ "github.com/getfider/fider/app/services/sqlstore/postgres"
_ "github.com/getfider/fider/app/services/userlist"
_ "github.com/getfider/fider/app/services/webhook"
)

//RunServer starts the Fider Server
//Returns an exitcode, 0 for OK and 1 for ERROR
// RunServer starts the Fider Server
// Returns an exitcode, 0 for OK and 1 for ERROR
func RunServer() int {
svcs := bus.Init()
ctx := log.WithProperty(context.Background(), log.PropertyKeyTag, "BOOTSTRAP")
Expand Down
11 changes: 11 additions & 0 deletions app/handlers/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import (

"github.com/getfider/fider/app/actions"
"github.com/getfider/fider/app/models/cmd"
"github.com/getfider/fider/app/models/dto"
"github.com/getfider/fider/app/models/entity"
"github.com/getfider/fider/app/models/query"
"github.com/getfider/fider/app/pkg/bus"
"github.com/getfider/fider/app/pkg/env"
"github.com/getfider/fider/app/pkg/web"
"github.com/getfider/fider/app/tasks"
)

// GeneralSettingsPage is the general settings page
Expand Down Expand Up @@ -59,6 +62,14 @@ func UpdateSettings() web.HandlerFunc {
return c.Failure(err)
}

// Handle userlist.
if env.Config.UserList.Enabled {
c.Enqueue(tasks.UserListUpdateCompany(&dto.UserListUpdateCompany{
TenantID: c.Tenant().ID,
Name: action.Title,
}))
}

return c.Ok(web.Map{})
}
}
Expand Down
20 changes: 20 additions & 0 deletions app/handlers/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/getfider/fider/app/models/cmd"
"github.com/getfider/fider/app/pkg/bus"
"github.com/getfider/fider/app/pkg/env"

"github.com/getfider/fider/app/tasks"

Expand Down Expand Up @@ -65,6 +66,10 @@ func VerifyChangeEmailKey() web.HandlerFunc {
return c.Failure(err)
}

if env.Config.UserList.Enabled {
c.Enqueue(tasks.UserListUpdateUser(c.User().ID, "", result.Email))
}

return c.Redirect(c.BaseURL() + "/settings")
}
}
Expand Down Expand Up @@ -112,6 +117,10 @@ func UpdateUserSettings() web.HandlerFunc {
return c.Failure(err)
}

if env.Config.UserList.Enabled {
c.Enqueue(tasks.UserListUpdateUser(c.User().ID, action.Name, ""))
}

return c.Ok(web.Map{})
}
}
Expand All @@ -133,6 +142,11 @@ func ChangeUserRole() web.HandlerFunc {
return c.Failure(err)
}

// Handle userlist
if env.Config.UserList.Enabled {
c.Enqueue(tasks.UserListAddOrRemoveUser(action.UserID, action.Role))
}

return c.Ok(web.Map{})
}
}
Expand All @@ -145,6 +159,12 @@ func DeleteUser() web.HandlerFunc {
}

c.RemoveCookie(web.CookieAuthName)

// Handle userlist (easiest way is to demote them which will remove them from the userlist)
if env.Config.UserList.Enabled {
c.Enqueue(tasks.UserListAddOrRemoveUser(c.User().ID, enum.RoleVisitor))
}

return c.Ok(web.Map{})
}
}
Expand Down
5 changes: 5 additions & 0 deletions app/handlers/signup.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ func VerifySignUpKey() web.HandlerFunc {
return c.Failure(err)
}

// Handle userlist.
if env.Config.UserList.Enabled {
c.Enqueue(tasks.UserListCreateCompany(*c.Tenant(), *user))
}

webutil.AddAuthUserCookie(c, user)

c.Enqueue(tasks.SendWelcomeEmail(user.Name, user.Email, c.BaseURL()))
Expand Down
20 changes: 20 additions & 0 deletions app/handlers/webhooks/paddle.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ import (

"github.com/getfider/fider/app/models/cmd"
"github.com/getfider/fider/app/models/dto"
"github.com/getfider/fider/app/models/enum"
"github.com/getfider/fider/app/pkg/bus"
"github.com/getfider/fider/app/pkg/env"
"github.com/getfider/fider/app/pkg/errors"
"github.com/getfider/fider/app/pkg/log"
"github.com/getfider/fider/app/pkg/web"
"github.com/getfider/fider/app/tasks"
)

// IncomingPaddleWebhook handles all incoming requests from Paddle Webhooks
Expand Down Expand Up @@ -66,6 +68,15 @@ func handlePaddleSubscriptionCreated(c *web.Context, params url.Values) error {
return c.Failure(err)
}

// Handle userlist.
if env.Config.UserList.Enabled {
c.Enqueue(tasks.UserListUpdateCompany(&dto.UserListUpdateCompany{
TenantID: passthrough.TenantID,
BillingStatus: enum.BillingActive,
Name: c.Tenant().Name,
}))
}

return c.Ok(web.Map{})
}

Expand All @@ -91,6 +102,15 @@ func handlePaddleSubscriptionCancelled(c *web.Context, params url.Values) error
return c.Failure(err)
}

// Handle userlist.
if env.Config.UserList.Enabled {
c.Enqueue(tasks.UserListUpdateCompany(&dto.UserListUpdateCompany{
TenantID: passthrough.TenantID,
BillingStatus: enum.BillingCancelled,
Name: c.Tenant().Name,
}))
}

return c.Ok(web.Map{})
}

Expand Down
13 changes: 13 additions & 0 deletions app/jobs/lock_expired_tenants_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package jobs
import (
"github.com/getfider/fider/app/models/cmd"
"github.com/getfider/fider/app/models/dto"
"github.com/getfider/fider/app/models/enum"
"github.com/getfider/fider/app/pkg/bus"
"github.com/getfider/fider/app/pkg/env"
"github.com/getfider/fider/app/pkg/log"
)

Expand All @@ -25,5 +27,16 @@ func (e LockExpiredTenantsJobHandler) Run(ctx Context) error {
"Count": c.NumOfTenantsLocked,
})

// Handle userlist
if env.Config.UserList.Enabled && c.NumOfTenantsLocked > 0 {
for _, tenant := range c.TenantsLocked {
err := bus.Dispatch(ctx, &cmd.UserListUpdateCompany{TenantId: tenant, BillingStatus: enum.BillingCancelled})
if err != nil {
return err
}
}

}

return nil
}
1 change: 1 addition & 0 deletions app/models/cmd/billing.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ type CancelBillingSubscription struct {
type LockExpiredTenants struct {
//Output
NumOfTenantsLocked int64
TenantsLocked []int
}
32 changes: 32 additions & 0 deletions app/models/cmd/userlist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cmd

import "github.com/getfider/fider/app/models/enum"

type UserListCreateCompany struct {
Name string
TenantId int
SignedUpAt string
BillingStatus string
Subdomain string
UserId int
UserEmail string
UserName string
}

type UserListUpdateCompany struct {
TenantId int
Name string
BillingStatus enum.BillingStatus
}

type UserListUpdateUser struct {
Id int
TenantId int
Email string
Name string
}

type UserListHandleRoleChange struct {
Id int
Role enum.Role
}
9 changes: 9 additions & 0 deletions app/models/dto/userlist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package dto

import "github.com/getfider/fider/app/models/enum"

type UserListUpdateCompany struct {
TenantID int
Name string
BillingStatus enum.BillingStatus
}
12 changes: 12 additions & 0 deletions app/pkg/dbx/setup.sql
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,15 @@ INSERT INTO users (name, email, tenant_id, created_at, role, status, avatar_type
VALUES ('The Hulk', '[email protected]', 2, now(), 1, 1, 2, '');
INSERT INTO user_providers (user_id, tenant_id, provider, provider_uid, created_at)
VALUES (5, 2, 'google', 'GO1111', now());

-- Create a tenant that has reached the end of it's trial period
INSERT INTO tenants (name, subdomain, created_at, cname, invitation, welcome_message, status, is_private, custom_css, logo_bkey, locale, is_email_auth_allowed)
VALUES ('Trial Expired', 'trial-expired', now(), 'feedback.trial-expired.com', '', '', 1, false, '', '', 'en', true);
INSERT INTO tenants_billing (tenant_id, paddle_plan_id, paddle_subscription_id, status, subscription_ends_at, trial_ends_at)
VALUES (3, 1, 1,1, now(), CURRENT_DATE - INTERVAL '10 days');
INSERT INTO users (name, email, tenant_id, created_at, role, status, avatar_type, avatar_bkey)
VALUES ('Trial Expired', '[email protected]', 3, now(), 3, 1, 2, '');
INSERT INTO user_providers (user_id, tenant_id, provider, provider_uid, created_at)
VALUES (6, 3, 'facebook', 'FB3333', now());


4 changes: 4 additions & 0 deletions app/pkg/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ type config struct {
CDN struct {
Host string `env:"CDN_HOST"`
}
UserList struct {
Enabled bool `env:"USER_LIST_ENABLED,default=false"`
ApiKey string `env:"USER_LIST_APIKEY"`
}
Log struct {
Level string `env:"LOG_LEVEL,default=INFO"`
Structured bool `env:"LOG_STRUCTURED,default=false"`
Expand Down
1 change: 1 addition & 0 deletions app/services/sqlstore/postgres/billing.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ func lockExpiredTenants(ctx context.Context, c *cmd.LockExpiredTenants) error {
}

c.NumOfTenantsLocked = count
c.TenantsLocked = ids
}

return nil
Expand Down
24 changes: 24 additions & 0 deletions app/services/sqlstore/postgres/billing_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package postgres_test

import (
"testing"

"github.com/getfider/fider/app/models/cmd"

. "github.com/getfider/fider/app/pkg/assert"
"github.com/getfider/fider/app/pkg/bus"
)

func TestLockExpiredTenants_ShouldTriggerForOneTenant(t *testing.T) {
ctx := SetupDatabaseTest(t)
defer TeardownDatabaseTest()

// There is a tenant with an expired trial setup in the seed for the test database.
q := &cmd.LockExpiredTenants{}

err := bus.Dispatch(ctx, q)
Expect(err).IsNil()
Expect(q.NumOfTenantsLocked).Equals(int64(1))
Expect(q.TenantsLocked).Equals([]int{3})

}
2 changes: 1 addition & 1 deletion app/services/sqlstore/postgres/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func TestUserStorage_Register(t *testing.T) {
err = bus.Dispatch(demoTenantCtx, getUser)
Expect(err).IsNil()

Expect(getUser.Result.ID).Equals(int(6))
Expect(getUser.Result.ID).Equals(int(7))
Expect(getUser.Result.Role).Equals(enum.RoleCollaborator)
Expect(getUser.Result.Name).Equals("Rob Stark")
Expect(getUser.Result.Email).Equals("[email protected]")
Expand Down
41 changes: 41 additions & 0 deletions app/services/userlist/mocks/mockUserQueryService.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package userlist_mock

import (
"context"

"github.com/getfider/fider/app/models/entity"
"github.com/getfider/fider/app/models/enum"
"github.com/getfider/fider/app/models/query"
"github.com/getfider/fider/app/pkg/bus"
)

type Service struct{}

func (s Service) Name() string {
return "PostgreSQL"
}

func (s Service) Category() string {
return "sqlstore"
}

func (s Service) Enabled() bool {
return true
}

func (s Service) Init() {
bus.AddHandler(GetUserByID)
}

func GetUserByID(ctx context.Context, q *query.GetUserByID) error {
q.Result = &entity.User{
ID: 1,
Name: "John Doe",
Email: "[email protected]",
Tenant: &entity.Tenant{ID: 1, Name: "Example Tenant"},
Role: enum.RoleAdministrator,
Providers: []*entity.UserProvider{},
Status: enum.UserActive,
}
return nil
}
Loading

0 comments on commit 142232d

Please sign in to comment.