func makeFakeWriterMetadataFuture(t *testing.T) writerMetadataFuture { wmd := WriterMetadata{ // This needs to be list format so it fails to compile if new fields // are added, effectively checking at compile time whether new fields // have been added []byte{0xa, 0xb}, "uid1", []keybase1.UID{"uid1", "uid2"}, nil, FakeTlfID(1, false), NullBranchID, 0xa, 100, 99, 101, WriterMetadataExtra{}, } wkb := makeFakeTLFWriterKeyBundleFuture(t) sa, _ := libkb.NormalizeSocialAssertion("foo@twitter") return writerMetadataFuture{ wmd, tlfWriterKeyGenerationsFuture{&wkb}, writerMetadataExtraFuture{ WriterMetadataExtra{ // This needs to be list format so it fails to compile if new // fields are added, effectively checking at compile time // whether new fields have been added []keybase1.SocialAssertion{sa}, codec.UnknownFieldSetHandler{}, }, makeExtraOrBust("WriterMetadata", t), }, } }
// AddNewAssertionForTest makes newAssertion, which should be a single // assertion that doesn't already resolve to anything, resolve to the // same UID as oldAssertion, which should be an arbitrary assertion // that does already resolve to something. It only applies to the // given config. func AddNewAssertionForTest( config Config, oldAssertion, newAssertion string) error { kbd, ok := config.KeybaseDaemon().(*KeybaseDaemonLocal) if !ok { return errors.New("Bad keybase daemon") } uid, err := kbd.addNewAssertionForTest(oldAssertion, newAssertion) if err != nil { return err } // Let the mdserver know about the name change md, ok := config.MDServer().(*MDServerLocal) if !ok { return errors.New("Bad md server") } // If this function is called multiple times for different // configs, it may end up invoking the following call more than // once on the shared md databases. That's ok though, it's an // idempotent call. newSocialAssertion, ok := libkb.NormalizeSocialAssertion(newAssertion) if !ok { return fmt.Errorf("%s couldn't be parsed as a social assertion", newAssertion) } if err := md.addNewAssertionForTest(uid, newSocialAssertion); err != nil { return fmt.Errorf("Couldn't update md server: %v", err) } return nil }
func (ra resolvableAssertion) resolve(ctx context.Context) ( nameUIDPair, keybase1.SocialAssertion, error) { if ra.assertion == PublicUIDName { return nameUIDPair{}, keybase1.SocialAssertion{}, fmt.Errorf("Invalid name %s", ra.assertion) } name, uid, err := ra.resolver.Resolve(ctx, ra.assertion) if err == nil && ra.mustBeUser != keybase1.UID("") && ra.mustBeUser != uid { // Force an unresolved assertion sinced the forced user doesn't match err = NoSuchUserError{ra.assertion} } switch err := err.(type) { default: return nameUIDPair{}, keybase1.SocialAssertion{}, err case nil: return nameUIDPair{ name: name, uid: uid, }, keybase1.SocialAssertion{}, nil case NoSuchUserError: if !ra.sharingBeforeSignupEnabled { return nameUIDPair{}, keybase1.SocialAssertion{}, err } socialAssertion, ok := libkb.NormalizeSocialAssertion(ra.assertion) if !ok { return nameUIDPair{}, keybase1.SocialAssertion{}, err } return nameUIDPair{}, socialAssertion, nil } }
// TODO: this function can likely be replaced with a call to // AssertionParseAndOnly when CORE-2967 and CORE-2968 are fixed. func normalizeAssertionOrName(s string) (string, error) { if libkb.CheckUsername.F(s) { return libkb.NewNormalizedUsername(s).String(), nil } // TODO: this fails for http and https right now (see CORE-2968). socialAssertion, isSocialAssertion := libkb.NormalizeSocialAssertion(s) if isSocialAssertion { return socialAssertion.String(), nil } if expr, err := libkb.AssertionParseAndOnly(s); err == nil { // If the expression only contains a single url, make sure // it's not a just considered a single keybase username. If // it is, then some non-username slipped into the default // "keybase" case and should be considered an error. urls := expr.CollectUrls(nil) if len(urls) == 1 && urls[0].IsKeybase() { return "", NoSuchUserError{s} } // Normalize and return. Ideally `AssertionParseAndOnly` // would normalize for us, but that doesn't work yet, so for // now we'll just lower-case. This will incorrectly lower // case http/https/web assertions, as well as case-sensitive // social assertions in AND expressions. TODO: see CORE-2967. return strings.ToLower(s), nil } return "", BadTLFNameError{s} }
// Test that WriterMetadata has only a fixed (frozen) set of fields. func TestWriterMetadataEncodedFields(t *testing.T) { sa1, _ := libkb.NormalizeSocialAssertion("uid1@twitter") sa2, _ := libkb.NormalizeSocialAssertion("uid2@twitter") // Usually exactly one of Writers/WKeys is filled in, but we // fill in both here for testing. wm := WriterMetadata{ ID: FakeTlfID(0xa, false), Writers: []keybase1.UID{"uid1", "uid2"}, WKeys: TLFWriterKeyGenerations{{}}, Extra: WriterMetadataExtra{ UnresolvedWriters: []keybase1.SocialAssertion{sa1, sa2}, }, } c := NewCodecMsgpack() buf, err := c.Encode(wm) require.NoError(t, err) var m map[string]interface{} err = c.Decode(buf, &m) require.NoError(t, err) expectedFields := []string{ "BID", "DiskUsage", "ID", "LastModifyingWriter", "RefBytes", "UnrefBytes", "WFlags", "WKeys", "Writers", "data", "x", } var fields []string for field := range m { fields = append(fields, field) } sort.Strings(fields) require.Equal(t, expectedFields, fields) }
func (e *FavoriteAdd) checkInviteNeeded(ctx *Context) error { defer func() { close(e.checkInviteDone) }() // If not folder creator, do nothing. if !e.arg.Folder.Created { return nil } for _, user := range strings.Split(e.arg.Folder.Name, ",") { assertion, ok := libkb.NormalizeSocialAssertion(user) if !ok { e.G().Log.Debug("not a social assertion: %s", user) continue } e.G().Log.Debug("social assertion found in FavoriteAdd folder name: %s", assertion) e.G().Log.Debug("requesting an invitation for %s", assertion) inv, err := libkb.GenerateInvitationCodeForAssertion(e.G(), assertion, libkb.InviteArg{}) if err != nil { return err } e.G().Log.Debug("invitation requested, informing folder creator with result") arg := keybase1.DisplayTLFCreateWithInviteArg{ FolderName: e.arg.Folder.Name, Assertion: assertion.String(), SocialAssertion: assertion, IsPrivate: e.arg.Folder.Private, Throttled: inv.Throttled, InviteLink: inv.Link(), } if err := ctx.IdentifyUI.DisplayTLFCreateWithInvite(arg); err != nil { return err } } return nil }
func makeFakeRootMetadataFuture(t *testing.T) *rootMetadataFuture { wmf := makeFakeWriterMetadataFuture(t) rkb := makeFakeTLFReaderKeyBundleFuture(t) h, err := DefaultHash([]byte("fake buf")) require.NoError(t, err) sa, _ := libkb.NormalizeSocialAssertion("bar@github") rmf := rootMetadataFuture{ wmf, rootMetadataWrapper{ RootMetadata{ // This needs to be list format so it fails to compile if new // fields are added, effectively checking at compile time // whether new fields have been added WriterMetadata{}, SignatureInfo{ 100, []byte{0xc}, MakeFakeVerifyingKeyOrBust("fake kid"), }, "uid1", 0xb, 5, MdID{h}, nil, []keybase1.SocialAssertion{sa}, nil, codec.UnknownFieldSetHandler{}, PrivateMetadata{}, nil, sync.RWMutex{}, MdID{}, }, }, []*tlfReaderKeyBundleFuture{&rkb}, makeExtraOrBust("RootMetadata", t), } return &rmf }