mirror of
https://github.com/matrix-org/dendrite.git
synced 2026-01-16 10:33:11 -06:00
Initial move of send join over to gmsl
This commit is contained in:
parent
3ca9859bb6
commit
09540c7de6
|
|
@ -16,7 +16,6 @@ package routing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
@ -240,131 +239,73 @@ func SendJoin(
|
||||||
JSON: spec.InternalServerError{},
|
JSON: spec.InternalServerError{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
verImpl, err := gomatrixserverlib.GetRoomVersion(roomVersion)
|
|
||||||
|
input := gomatrixserverlib.HandleSendJoinInput{
|
||||||
|
Context: httpReq.Context(),
|
||||||
|
RoomID: roomID,
|
||||||
|
EventID: eventID,
|
||||||
|
EventContent: request.Content(),
|
||||||
|
RoomVersion: roomVersion,
|
||||||
|
RequestOrigin: request.Origin(),
|
||||||
|
LocalServerName: cfg.Matrix.ServerName,
|
||||||
|
KeyID: cfg.Matrix.KeyID,
|
||||||
|
PrivateKey: cfg.Matrix.PrivateKey,
|
||||||
|
Verifier: keys,
|
||||||
|
RoomQuerier: &JoinRoomQuerier{roomserver: rsAPI},
|
||||||
|
}
|
||||||
|
response, err := gomatrixserverlib.HandleSendJoin(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return util.JSONResponse{
|
// TODO: Double check this reflects old logic
|
||||||
Code: http.StatusInternalServerError,
|
switch e := err.(type) {
|
||||||
JSON: spec.UnsupportedRoomVersion(
|
case nil:
|
||||||
fmt.Sprintf("QueryRoomVersionForRoom returned unknown room version: %s", roomVersion),
|
case spec.InternalServerError:
|
||||||
),
|
util.GetLogger(httpReq.Context()).WithError(err)
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusInternalServerError,
|
||||||
|
JSON: spec.InternalServerError{},
|
||||||
|
}
|
||||||
|
case spec.MatrixError:
|
||||||
|
util.GetLogger(httpReq.Context()).WithError(err)
|
||||||
|
code := http.StatusInternalServerError
|
||||||
|
switch e.ErrCode {
|
||||||
|
case spec.ErrorForbidden:
|
||||||
|
code = http.StatusForbidden
|
||||||
|
case spec.ErrorNotFound:
|
||||||
|
code = http.StatusNotFound
|
||||||
|
case spec.ErrorUnsupportedRoomVersion:
|
||||||
|
code = http.StatusInternalServerError
|
||||||
|
case spec.ErrorBadJSON:
|
||||||
|
code = http.StatusBadRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: code,
|
||||||
|
JSON: e,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
util.GetLogger(httpReq.Context()).WithError(err)
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: spec.Unknown("unknown error"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
event, err := verImpl.NewEventFromUntrustedJSON(request.Content())
|
if response == nil {
|
||||||
if err != nil {
|
util.GetLogger(httpReq.Context()).Error("gmsl.HandleMakeJoin returned invalid response")
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: spec.BadJSON("The request body could not be decoded into valid JSON: " + err.Error()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that a state key is provided.
|
|
||||||
if event.StateKey() == nil || event.StateKeyEquals("") {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: spec.BadJSON("No state key was provided in the join event."),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !event.StateKeyEquals(event.Sender()) {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: spec.BadJSON("Event state key must match the event sender."),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the sender belongs to the server that is sending us
|
|
||||||
// the request. By this point we've already asserted that the sender
|
|
||||||
// and the state key are equal so we don't need to check both.
|
|
||||||
sender, err := spec.NewUserID(event.Sender(), true)
|
|
||||||
if err != nil {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusForbidden,
|
|
||||||
JSON: spec.Forbidden("The sender of the join is invalid"),
|
|
||||||
}
|
|
||||||
} else if sender.Domain() != request.Origin() {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusForbidden,
|
|
||||||
JSON: spec.Forbidden("The sender does not match the server that originated the request"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the room ID is correct.
|
|
||||||
if event.RoomID() != roomID.String() {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: spec.BadJSON(
|
|
||||||
fmt.Sprintf(
|
|
||||||
"The room ID in the request path (%q) must match the room ID in the join event JSON (%q)",
|
|
||||||
roomID, event.RoomID(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the event ID is correct.
|
|
||||||
if event.EventID() != eventID {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: spec.BadJSON(
|
|
||||||
fmt.Sprintf(
|
|
||||||
"The event ID in the request path (%q) must match the event ID in the join event JSON (%q)",
|
|
||||||
eventID, event.EventID(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that this is in fact a join event
|
|
||||||
membership, err := event.Membership()
|
|
||||||
if err != nil {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: spec.BadJSON("missing content.membership key"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if membership != spec.Join {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: spec.BadJSON("membership must be 'join'"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the event is signed by the server sending the request.
|
|
||||||
redacted, err := verImpl.RedactEventJSON(event.JSON())
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Errorf("XXX: join.go")
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: spec.BadJSON("The event JSON could not be redacted"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
verifyRequests := []gomatrixserverlib.VerifyJSONRequest{{
|
|
||||||
ServerName: sender.Domain(),
|
|
||||||
Message: redacted,
|
|
||||||
AtTS: event.OriginServerTS(),
|
|
||||||
StrictValidityChecking: true,
|
|
||||||
}}
|
|
||||||
verifyResults, err := keys.VerifyJSONs(httpReq.Context(), verifyRequests)
|
|
||||||
if err != nil {
|
|
||||||
util.GetLogger(httpReq.Context()).WithError(err).Error("keys.VerifyJSONs failed")
|
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusInternalServerError,
|
Code: http.StatusInternalServerError,
|
||||||
JSON: spec.InternalServerError{},
|
JSON: spec.InternalServerError{},
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if verifyResults[0].Error != nil {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusForbidden,
|
|
||||||
JSON: spec.Forbidden("Signature check failed: " + verifyResults[0].Error.Error()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the state and auth chain. We do this before we send the events
|
// Fetch the state and auth chain. We do this before we send the events
|
||||||
// on, in case this fails.
|
// on, in case this fails.
|
||||||
var stateAndAuthChainResponse api.QueryStateAndAuthChainResponse
|
var stateAndAuthChainResponse api.QueryStateAndAuthChainResponse
|
||||||
err = rsAPI.QueryStateAndAuthChain(httpReq.Context(), &api.QueryStateAndAuthChainRequest{
|
err = rsAPI.QueryStateAndAuthChain(httpReq.Context(), &api.QueryStateAndAuthChainRequest{
|
||||||
PrevEventIDs: event.PrevEventIDs(),
|
PrevEventIDs: response.JoinEvent.PrevEventIDs(),
|
||||||
AuthEventIDs: event.AuthEventIDs(),
|
AuthEventIDs: response.JoinEvent.AuthEventIDs(),
|
||||||
RoomID: roomID.String(),
|
RoomID: roomID.String(),
|
||||||
ResolveState: true,
|
ResolveState: true,
|
||||||
}, &stateAndAuthChainResponse)
|
}, &stateAndAuthChainResponse)
|
||||||
|
|
@ -389,84 +330,27 @@ func SendJoin(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the user is already in the room. If they're already in then
|
|
||||||
// there isn't much point in sending another join event into the room.
|
|
||||||
// Also check to see if they are banned: if they are then we reject them.
|
|
||||||
alreadyJoined := false
|
|
||||||
isBanned := false
|
|
||||||
for _, se := range stateAndAuthChainResponse.StateEvents {
|
|
||||||
if !se.StateKeyEquals(*event.StateKey()) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if membership, merr := se.Membership(); merr == nil {
|
|
||||||
alreadyJoined = (membership == spec.Join)
|
|
||||||
isBanned = (membership == spec.Ban)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if isBanned {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusForbidden,
|
|
||||||
JSON: spec.Forbidden("user is banned"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the membership content contains a user ID for a server that is not
|
|
||||||
// ours then we should kick it back.
|
|
||||||
var memberContent gomatrixserverlib.MemberContent
|
|
||||||
if err := json.Unmarshal(event.Content(), &memberContent); err != nil {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: spec.BadJSON(err.Error()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if memberContent.AuthorisedVia != "" {
|
|
||||||
_, domain, err := gomatrixserverlib.SplitID('@', memberContent.AuthorisedVia)
|
|
||||||
if err != nil {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: spec.BadJSON(fmt.Sprintf("The authorising username %q is invalid.", memberContent.AuthorisedVia)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if domain != cfg.Matrix.ServerName {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: spec.BadJSON(fmt.Sprintf("The authorising username %q does not belong to this server.", memberContent.AuthorisedVia)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sign the membership event. This is required for restricted joins to work
|
|
||||||
// in the case that the authorised via user is one of our own users. It also
|
|
||||||
// doesn't hurt to do it even if it isn't a restricted join.
|
|
||||||
signed := event.Sign(
|
|
||||||
string(cfg.Matrix.ServerName),
|
|
||||||
cfg.Matrix.KeyID,
|
|
||||||
cfg.Matrix.PrivateKey,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Send the events to the room server.
|
// Send the events to the room server.
|
||||||
// We are responsible for notifying other servers that the user has joined
|
// We are responsible for notifying other servers that the user has joined
|
||||||
// the room, so set SendAsServer to cfg.Matrix.ServerName
|
// the room, so set SendAsServer to cfg.Matrix.ServerName
|
||||||
if !alreadyJoined {
|
if !response.AlreadyJoined {
|
||||||
var response api.InputRoomEventsResponse
|
var rsResponse api.InputRoomEventsResponse
|
||||||
rsAPI.InputRoomEvents(httpReq.Context(), &api.InputRoomEventsRequest{
|
rsAPI.InputRoomEvents(httpReq.Context(), &api.InputRoomEventsRequest{
|
||||||
InputRoomEvents: []api.InputRoomEvent{
|
InputRoomEvents: []api.InputRoomEvent{
|
||||||
{
|
{
|
||||||
Kind: api.KindNew,
|
Kind: api.KindNew,
|
||||||
Event: &types.HeaderedEvent{PDU: signed},
|
Event: &types.HeaderedEvent{PDU: response.JoinEvent},
|
||||||
SendAsServer: string(cfg.Matrix.ServerName),
|
SendAsServer: string(cfg.Matrix.ServerName),
|
||||||
TransactionID: nil,
|
TransactionID: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, &response)
|
}, &rsResponse)
|
||||||
if response.ErrMsg != "" {
|
if rsResponse.ErrMsg != "" {
|
||||||
util.GetLogger(httpReq.Context()).WithField(logrus.ErrorKey, response.ErrMsg).Error("SendEvents failed")
|
util.GetLogger(httpReq.Context()).WithField(logrus.ErrorKey, rsResponse.ErrMsg).Error("SendEvents failed")
|
||||||
if response.NotAllowed {
|
if rsResponse.NotAllowed {
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusBadRequest,
|
Code: http.StatusBadRequest,
|
||||||
JSON: spec.Forbidden(response.ErrMsg),
|
JSON: spec.Forbidden(rsResponse.ErrMsg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
|
|
@ -489,7 +373,7 @@ func SendJoin(
|
||||||
StateEvents: types.NewEventJSONsFromHeaderedEvents(stateAndAuthChainResponse.StateEvents),
|
StateEvents: types.NewEventJSONsFromHeaderedEvents(stateAndAuthChainResponse.StateEvents),
|
||||||
AuthEvents: types.NewEventJSONsFromHeaderedEvents(stateAndAuthChainResponse.AuthChainEvents),
|
AuthEvents: types.NewEventJSONsFromHeaderedEvents(stateAndAuthChainResponse.AuthChainEvents),
|
||||||
Origin: cfg.Matrix.ServerName,
|
Origin: cfg.Matrix.ServerName,
|
||||||
Event: signed.JSON(),
|
Event: response.JoinEvent.JSON(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
go.mod
4
go.mod
|
|
@ -22,7 +22,7 @@ require (
|
||||||
github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e
|
github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e
|
||||||
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91
|
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530
|
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230517000105-1ff06fc8a6a2
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20230518142313-2f3c95fab59e
|
||||||
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a
|
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a
|
||||||
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66
|
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66
|
||||||
github.com/mattn/go-sqlite3 v1.14.16
|
github.com/mattn/go-sqlite3 v1.14.16
|
||||||
|
|
@ -34,7 +34,7 @@ require (
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/prometheus/client_golang v1.13.0
|
github.com/prometheus/client_golang v1.13.0
|
||||||
github.com/sirupsen/logrus v1.9.1
|
github.com/sirupsen/logrus v1.9.2
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.2
|
||||||
github.com/tidwall/gjson v1.14.4
|
github.com/tidwall/gjson v1.14.4
|
||||||
github.com/tidwall/sjson v1.2.5
|
github.com/tidwall/sjson v1.2.5
|
||||||
|
|
|
||||||
8
go.sum
8
go.sum
|
|
@ -323,8 +323,8 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 h1:s7fexw
|
||||||
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo=
|
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo=
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U=
|
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U=
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230517000105-1ff06fc8a6a2 h1:V36yCWt2CoSfI1xr6WYJ9Mb3eyl95SknMRLGFvEuYak=
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20230518142313-2f3c95fab59e h1:zdWOVsJZiwtvHX0HCFuElbz4qN3zfw7OQEfy3+LthEU=
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230517000105-1ff06fc8a6a2/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU=
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20230518142313-2f3c95fab59e/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU=
|
||||||
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a h1:awrPDf9LEFySxTLKYBMCiObelNx/cBuv/wzllvCCH3A=
|
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a h1:awrPDf9LEFySxTLKYBMCiObelNx/cBuv/wzllvCCH3A=
|
||||||
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a/go.mod h1:HchJX9oKMXaT2xYFs0Ha/6Zs06mxLU8k6F1ODnrGkeQ=
|
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a/go.mod h1:HchJX9oKMXaT2xYFs0Ha/6Zs06mxLU8k6F1ODnrGkeQ=
|
||||||
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y=
|
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y=
|
||||||
|
|
@ -444,8 +444,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/sirupsen/logrus v1.9.1 h1:Ou41VVR3nMWWmTiEUnj0OlsgOSCUFgsPAOl6jRIcVtQ=
|
github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y=
|
||||||
github.com/sirupsen/logrus v1.9.1/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
||||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue