Skip to content

Commit

Permalink
Add a possibility to use a magic token instead of real invites (#1)
Browse files Browse the repository at this point in the history
Add a possibility to use a magic token instead of real invites. To set the token use the `bypass-invites-token` flag. All invites which use this token will succeed.
  • Loading branch information
boreq authored and mixmix committed Nov 16, 2022
1 parent 0bbeeb1 commit 6d95e48
Show file tree
Hide file tree
Showing 13 changed files with 97 additions and 49 deletions.
2 changes: 1 addition & 1 deletion cmd/insert-user/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func main() {
}

r := repo.New(repoPath)
db, err := sqlite.Open(r)
db, err := sqlite.Open(r, nil)
check(err)
defer db.Close()

Expand Down
13 changes: 12 additions & 1 deletion cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ var (

httpsDomain string

bypassInvitesToken string

aliasesAsSubdomains bool

listenAddrDebug string
Expand Down Expand Up @@ -106,6 +108,8 @@ func initFlags() {

flag.StringVar(&httpsDomain, "https-domain", "", "which domain to use for TLS and AllowedHosts checks")

flag.StringVar(&bypassInvitesToken, "bypass-invites-token", "", "magic token which always allows the users to register")

flag.BoolVar(&flagPrintVersion, "version", false, "print version number and build date")

flag.Func("mode", "the privacy mode (values: open, community, restricted) determining room access controls", func(val string) error {
Expand Down Expand Up @@ -237,7 +241,7 @@ func runroomsrv() error {
}

// open the sqlite version of the roomdb
db, err := sqlite.Open(r)
db, err := sqlite.Open(r, bypassInvitesTokenOrNil())
if err != nil {
return fmt.Errorf("failed to initiate database: %w", err)
}
Expand Down Expand Up @@ -442,3 +446,10 @@ func (limitByPathAndAddr) Key(r *http.Request) string {

return k.String()
}

func bypassInvitesTokenOrNil() *string {
if bypassInvitesToken == "" {
return nil
}
return &bypassInvitesToken
}
2 changes: 1 addition & 1 deletion muxrpc/test/go/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func makeNamedTestBot(t testing.TB, name string, ctx context.Context, opts []roo
)

// could also use the mocks
db, err := sqlite.Open(repo.New(testPath))
db, err := sqlite.Open(repo.New(testPath), nil)
r.NoError(err)
t.Cleanup(func() {
if err := db.Close(); err != nil {
Expand Down
4 changes: 2 additions & 2 deletions roomdb/sqlite/aliases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestAliases(t *testing.T) {
testSig := make([]byte, 64)
rand.Read(testSig)

db, err := Open(tr)
db, err := Open(tr, nil)
require.NoError(t, err)

t.Run("not found", func(t *testing.T) {
Expand Down Expand Up @@ -111,7 +111,7 @@ func TestAliasesUniqueError(t *testing.T) {
os.RemoveAll(testRepo)
tr := repo.New(testRepo)

db, err := Open(tr)
db, err := Open(tr, nil)
r.NoError(err)

// fake feed for testing, looks ok at least
Expand Down
6 changes: 3 additions & 3 deletions roomdb/sqlite/auth_fallback_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func TestFallbackAuth(t *testing.T) {
r.Error(err)
}

db, err := Open(tr)
db, err := Open(tr, nil)
r.NoError(err, "failed to open database")

memberID, err := db.Members.Add(ctx, newMember, roomdb.RoleMember)
Expand Down Expand Up @@ -82,7 +82,7 @@ func TestFallbackAuthSetPassword(t *testing.T) {
r.Error(err)
}

db, err := Open(tr)
db, err := Open(tr, nil)
r.NoError(err, "failed to open database")

memberID, err := db.Members.Add(ctx, newMember, roomdb.RoleMember)
Expand Down Expand Up @@ -141,7 +141,7 @@ func TestFallbackAuthSetPasswordWithToken(t *testing.T) {
r.Error(err)
}

db, err := Open(tr)
db, err := Open(tr, nil)
r.NoError(err, "failed to open database")

alfID, err := db.Members.Add(ctx, alf, roomdb.RoleModerator)
Expand Down
6 changes: 3 additions & 3 deletions roomdb/sqlite/denied_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestDeniedKeys(t *testing.T) {

tr := repo.New(testRepo)

db, err := Open(tr)
db, err := Open(tr, nil)
require.NoError(t, err)

tf, err := refs.NewFeedRefFromBytes(bytes.Repeat([]byte("fooo"), 8), "nope")
Expand Down Expand Up @@ -95,7 +95,7 @@ func TestDeniedKeysUnique(t *testing.T) {

tr := repo.New(testRepo)

db, err := Open(tr)
db, err := Open(tr, nil)
require.NoError(t, err)

feedA, err := refs.NewFeedRefFromBytes(bytes.Repeat([]byte("b33f"), 8), refs.RefAlgoFeedSSB1)
Expand Down Expand Up @@ -124,7 +124,7 @@ func TestDeniedKeysByID(t *testing.T) {

tr := repo.New(testRepo)

db, err := Open(tr)
db, err := Open(tr, nil)
require.NoError(t, err)

feedA, err := refs.NewFeedRefFromBytes(bytes.Repeat([]byte("b33f"), 8), refs.RefAlgoFeedSSB1)
Expand Down
59 changes: 33 additions & 26 deletions roomdb/sqlite/invites.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ type Invites struct {
db *sql.DB

members Members

bypassInvitesToken *string
}

// Create creates a new invite for a new member. It returns the token or an error.
Expand Down Expand Up @@ -112,24 +114,37 @@ func (i Invites) Create(ctx context.Context, createdBy int64) (string, error) {
func (i Invites) Consume(ctx context.Context, token string, newMember refs.FeedRef) (roomdb.Invite, error) {
var inv roomdb.Invite

hashedToken, err := getHashedToken(token)
if err != nil {
return inv, err
}
err := transact(i.db, func(tx *sql.Tx) error {
if !i.matchesBypassInvitesToken(token) {
hashedToken, err := getHashedToken(token)
if err != nil {
return err
}

err = transact(i.db, func(tx *sql.Tx) error {
entry, err := models.Invites(
qm.Where("active = true AND hashed_token = ?", hashedToken),
qm.Load("CreatedByMember"),
).One(ctx, tx)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return roomdb.ErrNotFound
entry, err := models.Invites(
qm.Where("active = true AND hashed_token = ?", hashedToken),
qm.Load("CreatedByMember"),
).One(ctx, tx)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return roomdb.ErrNotFound
}
return err
}
return err

entry.Active = false
_, err = entry.Update(ctx, tx, boil.Whitelist("active"))
if err != nil {
return err
}

inv.ID = entry.ID
inv.CreatedAt = entry.CreatedAt
inv.CreatedBy.ID = entry.R.CreatedByMember.ID
inv.CreatedBy.Role = roomdb.Role(entry.R.CreatedByMember.Role)
}

_, err = i.members.add(ctx, tx, newMember, roomdb.RoleMember)
_, err := i.members.add(ctx, tx, newMember, roomdb.RoleMember)
var alreadyAdded roomdb.ErrAlreadyAdded
if err != nil {
if errors.As(err, &alreadyAdded) && alreadyAdded.Ref.Equal(newMember) {
Expand All @@ -139,18 +154,6 @@ func (i Invites) Consume(ctx context.Context, token string, newMember refs.FeedR
}
}

// invalidate the invite for consumption
entry.Active = false
_, err = entry.Update(ctx, tx, boil.Whitelist("active"))
if err != nil {
return err
}

inv.ID = entry.ID
inv.CreatedAt = entry.CreatedAt
inv.CreatedBy.ID = entry.R.CreatedByMember.ID
inv.CreatedBy.Role = roomdb.Role(entry.R.CreatedByMember.Role)

return nil
})

Expand Down Expand Up @@ -295,6 +298,10 @@ func (i Invites) Revoke(ctx context.Context, id int64) error {
})
}

func (i Invites) matchesBypassInvitesToken(token string) bool {
return i.bypassInvitesToken != nil && token == *i.bypassInvitesToken
}

const inviteTokenLength = 50

func getHashedToken(b64tok string) (string, error) {
Expand Down
32 changes: 31 additions & 1 deletion roomdb/sqlite/invites_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func TestInvites(t *testing.T) {
t.Error(err)
}

db, err := Open(tr)
db, err := Open(tr, nil)
require.NoError(t, err)

t.Run("try to consume invalid token", func(t *testing.T) {
Expand Down Expand Up @@ -156,3 +156,33 @@ func TestInvites(t *testing.T) {
r.Len(lst, 0, "expected no active invites")
})
}

func TestInvites_BypassInvitestToken(t *testing.T) {
ctx := context.Background()

testRepo := filepath.Join("testrun", t.Name())
os.RemoveAll(testRepo)
tr := repo.New(testRepo)

// fake feed for testing, looks ok at least
newMember := refs.FeedRef{ID: bytes.Repeat([]byte("acab"), 8), Algo: refs.RefAlgoFeedSSB1}

token := "magic token"

db, err := Open(tr, &token)
require.NoError(t, err)

t.Run("try to consume a magic token", func(t *testing.T) {
r := require.New(t)

lst, err := db.Invites.List(ctx)
r.NoError(err, "failed to list invites")
r.Len(lst, 0, "expected no active invites")

randToken := make([]byte, 32)
rand.Read(randToken)

_, err = db.Invites.Consume(ctx, token, newMember)
r.NoError(err, "expected no error for bypass invites token")
})
}
10 changes: 5 additions & 5 deletions roomdb/sqlite/members_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestMembers(t *testing.T) {

tr := repo.New(testRepo)

db, err := Open(tr)
db, err := Open(tr, nil)
require.NoError(t, err)

// broken feed (unknown algo)
Expand Down Expand Up @@ -94,7 +94,7 @@ func TestMembersUnique(t *testing.T) {

tr := repo.New(testRepo)

db, err := Open(tr)
db, err := Open(tr, nil)
require.NoError(t, err)

feedA, err := refs.NewFeedRefFromBytes(bytes.Repeat([]byte("1312"), 8), refs.RefAlgoFeedSSB1)
Expand Down Expand Up @@ -123,7 +123,7 @@ func TestMembersByID(t *testing.T) {

tr := repo.New(testRepo)

db, err := Open(tr)
db, err := Open(tr, nil)
require.NoError(t, err)

feedA, err := refs.NewFeedRefFromBytes(bytes.Repeat([]byte("1312"), 8), refs.RefAlgoFeedSSB1)
Expand Down Expand Up @@ -165,7 +165,7 @@ func TestMembersSetRole(t *testing.T) {

tr := repo.New(testRepo)

db, err := Open(tr)
db, err := Open(tr, nil)
require.NoError(t, err)

// create two users
Expand Down Expand Up @@ -253,7 +253,7 @@ func TestMembersAliases(t *testing.T) {

tr := repo.New(testRepo)

db, err := Open(tr)
db, err := Open(tr, nil)
require.NoError(t, err)

feedA, err := refs.NewFeedRefFromBytes(bytes.Repeat([]byte("1312"), 8), refs.RefAlgoFeedSSB1)
Expand Down
4 changes: 2 additions & 2 deletions roomdb/sqlite/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ type Database struct {
}

// Open looks for a database file 'fname'
func Open(r repo.Interface) (*Database, error) {
func Open(r repo.Interface, bypassInvitesToken *string) (*Database, error) {
fname := r.GetPath("roomdb")

if dir := filepath.Dir(fname); dir != "" {
Expand Down Expand Up @@ -116,7 +116,7 @@ func Open(r repo.Interface) (*Database, error) {
AuthWithSSB: AuthWithSSB{db},
Config: Config{db},
DeniedKeys: DeniedKeys{db},
Invites: Invites{db: db, members: ml},
Invites: Invites{db: db, members: ml, bypassInvitesToken: bypassInvitesToken},
Notices: Notices{db},
Members: ml,
PinnedNotices: PinnedNotices{db},
Expand Down
2 changes: 1 addition & 1 deletion roomdb/sqlite/new_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestSchema(t *testing.T) {

tr := repo.New(testRepo)

db, err := Open(tr)
db, err := Open(tr, nil)
require.NoError(t, err)

err = db.Close()
Expand Down
4 changes: 2 additions & 2 deletions roomdb/sqlite/notices_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestNoticesCRUD(t *testing.T) {

tr := repo.New(testRepo)

db, err := Open(tr)
db, err := Open(tr, nil)
r.NoError(err)

// boil.DebugWriter = os.Stderr
Expand Down Expand Up @@ -87,7 +87,7 @@ func TestPinnedNotices(t *testing.T) {

tr := repo.New(testRepo)

db, err := Open(tr)
db, err := Open(tr, nil)
r.NoError(err)

t.Run("defaults", func(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion roomdb/sqlite/roomconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func TestRoomConfig(t *testing.T) {

tr := repo.New(testRepo)

db, err := Open(tr)
db, err := Open(tr, nil)
r.NoError(err)

// make sure we have the expected default
Expand Down

0 comments on commit 6d95e48

Please sign in to comment.