Compare commits
3
Commits
51b151aa26
..
next
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc8aa6bb96 | ||
|
|
bc7ef8240b | ||
|
|
8afd873813 |
+8
-4
@@ -33,14 +33,18 @@ RUN golangci-lint run --config .golangci.yml ./...
|
|||||||
# golang:1.24.13-bookworm, 2026-10-06
|
# golang:1.24.13-bookworm, 2026-10-06
|
||||||
FROM golang@sha256:1a6d4452c65dea36aac2e2d606b01b4a029ec90cc1ae53890540ce6173ea77ac AS test
|
FROM golang@sha256:1a6d4452c65dea36aac2e2d606b01b4a029ec90cc1ae53890540ce6173ea77ac AS test
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY go.mod go.sum ./
|
|
||||||
RUN go mod download
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN mkdir -p web/dist && touch web/dist/index.html web/dist/style.css web/dist/app.js
|
RUN mkdir -p web/dist && touch web/dist/index.html web/dist/style.css web/dist/app.js
|
||||||
# -p 4 because test runs on a shared build host cap their parallelism.
|
# -p 4 because test runs on a shared build host cap their parallelism.
|
||||||
RUN go test -p 4 -timeout 90s -race -cover ./... || \
|
# The modules download in this RUN rather than a layer of their own, because
|
||||||
|
# exporting a layer that holds them is slow. Nothing reads them or the build
|
||||||
|
# cache afterwards, so go clean removes both.
|
||||||
|
RUN set -e; \
|
||||||
|
go mod download; \
|
||||||
|
go test -p 4 -timeout 90s -race -cover ./... || \
|
||||||
{ echo "--- Rerunning with -v for details ---"; \
|
{ echo "--- Rerunning with -v for details ---"; \
|
||||||
go test -p 4 -timeout 90s -race -v ./...; exit 1; }
|
go test -p 4 -timeout 90s -race -v ./...; exit 1; }; \
|
||||||
|
go clean -cache -modcache
|
||||||
|
|
||||||
# Build stage. Nothing is wanted from either phase above; the copies
|
# Build stage. Nothing is wanted from either phase above; the copies
|
||||||
# are what make BuildKit build them first, so this stage cannot run
|
# are what make BuildKit build them first, so this stage cannot run
|
||||||
|
|||||||
@@ -1056,23 +1056,6 @@ func (database *Database) GetChannelMemberIDs(
|
|||||||
return scanInt64s(rows)
|
return scanInt64s(rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSessionChannelIDs returns channel IDs for a session.
|
|
||||||
func (database *Database) GetSessionChannelIDs(
|
|
||||||
ctx context.Context,
|
|
||||||
sessionID int64,
|
|
||||||
) ([]int64, error) {
|
|
||||||
rows, err := database.conn.QueryContext(ctx,
|
|
||||||
`SELECT channel_id FROM channel_members
|
|
||||||
WHERE session_id = ?`, sessionID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf(
|
|
||||||
"get session channel ids: %w", err,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return scanInt64s(rows)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertMessage stores a message and returns its DB ID.
|
// InsertMessage stores a message and returns its DB ID.
|
||||||
// toSessionID is the session a DM or INVITE is sent to and
|
// toSessionID is the session a DM or INVITE is sent to and
|
||||||
// toChannelID the channel a channel message is sent to;
|
// toChannelID the channel a channel message is sent to;
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
"sneak.berlin/go/neoirc/internal/dbtest"
|
||||||
"sneak.berlin/go/neoirc/internal/ircserver"
|
"sneak.berlin/go/neoirc/internal/ircserver"
|
||||||
"sneak.berlin/go/neoirc/internal/service"
|
"sneak.berlin/go/neoirc/internal/service"
|
||||||
)
|
)
|
||||||
@@ -583,8 +585,10 @@ func ownSessionCopies(
|
|||||||
|
|
||||||
// aliceWithHTTPClient connects alice to the IRC listener and
|
// aliceWithHTTPClient connects alice to the IRC listener and
|
||||||
// has her join #chan, which bob is on too, then adds an HTTP API
|
// has her join #chan, which bob is on too, then adds an HTTP API
|
||||||
// client to her session with the password her connection set,
|
// client to her session with a password, as POST /api/v1/login
|
||||||
// as POST /api/v1/login does. It returns her connection, bob's
|
// does. It stores that password without sending PASS. It hashes
|
||||||
|
// at bcrypt.MinCost, and a login compares at the cost stored in
|
||||||
|
// the hash, so both are fast. It returns her connection, bob's
|
||||||
// connection, her session and her HTTP API client.
|
// connection, her session and her HTTP API client.
|
||||||
func aliceWithHTTPClient(
|
func aliceWithHTTPClient(
|
||||||
t *testing.T, env *testEnv,
|
t *testing.T, env *testEnv,
|
||||||
@@ -594,15 +598,24 @@ func aliceWithHTTPClient(
|
|||||||
const password = "alicepass"
|
const password = "alicepass"
|
||||||
|
|
||||||
alice := env.dial(t)
|
alice := env.dial(t)
|
||||||
alice.send("PASS " + password)
|
|
||||||
alice.register("alice")
|
alice.register("alice")
|
||||||
// Registration stores the password before the JOIN runs.
|
|
||||||
alice.joinAndDrain("#chan")
|
alice.joinAndDrain("#chan")
|
||||||
|
|
||||||
bob := env.dial(t)
|
bob := env.dial(t)
|
||||||
bob.register("bob")
|
bob.register("bob")
|
||||||
bob.joinAndDrain("#chan")
|
bob.joinAndDrain("#chan")
|
||||||
|
|
||||||
|
hash, err := bcrypt.GenerateFromPassword(
|
||||||
|
[]byte(password), bcrypt.MinCost,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("hash password: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dbtest.Exec(t, env.dbURL,
|
||||||
|
"UPDATE sessions SET password_hash = '"+string(hash)+
|
||||||
|
"' WHERE nick = 'alice'")
|
||||||
|
|
||||||
sessionID, httpClientID, _, err := env.database.LoginUser(
|
sessionID, httpClientID, _, err := env.database.LoginUser(
|
||||||
t.Context(), "alice", password, "127.0.0.1", "localhost",
|
t.Context(), "alice", password, "127.0.0.1", "localhost",
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user