diff options
| author | tjp <tjp@ctrl-c.club> | 2024-01-08 11:10:24 -0700 |
|---|---|---|
| committer | tjp <tjp@ctrl-c.club> | 2024-01-08 11:10:24 -0700 |
| commit | a90327bcc0f46171e30a4a549fb5b44f8e91e303 (patch) | |
| tree | 8595b256c8e9fa2232525199c51021e0efbebac4 /identity.go | |
| parent | 230933ee0e4bce6ddf25e0816fff0bd30e3c8864 (diff) | |
identity management and use
Diffstat (limited to 'identity.go')
| -rw-r--r-- | identity.go | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/identity.go b/identity.go new file mode 100644 index 0000000..891c01b --- /dev/null +++ b/identity.go @@ -0,0 +1,205 @@ +package main + +import ( + "bytes" + "crypto/tls" + "errors" + "fmt" + "io" + "net/url" + "os" + "strings" +) + +type Identities struct { + ByName map[string]*tls.Config + ByDomain map[string]*tls.Config + ByPage map[string]*tls.Config + ByFolder map[string]*tls.Config +} + +func findIdentity(state *BrowserState, prefix string) (string, error) { + found := 0 + value := "" + for name := range state.Identities.ByName { + if strings.HasPrefix(name, prefix) { + found += 1 + value = name + } + } + + switch found { + case 0: + return "", errors.New("no matching identity found") + case 1: + return value, nil + default: + return "", fmt.Errorf("too ambiguous - that name matched %d identities", found) + } +} + +func (ids Identities) Get(u *url.URL) *tls.Config { + if conf, ok := ids.ByPage[u.String()]; ok { + return conf + } + + pathsegments := strings.Split(strings.TrimLeft(u.Path, "/"), "/") + for len(pathsegments) > 0 { + pathsegments = pathsegments[0 : len(pathsegments)-1] + if conf, ok := ids.ByFolder[u.Hostname()+"/"+strings.Join(pathsegments, "/")]; ok { + return conf + } + } + + if conf, ok := ids.ByDomain[u.Hostname()]; ok { + return conf + } + + return nil +} + +func IdentityCreate(state *BrowserState, name string) error { + ident, err := createIdentity(state, name) + if err != nil { + return err + } + state.Identities.ByName[name] = ident + return saveIdentities(state.Identities) +} + +func IdentityList(state *BrowserState) error { + buf := &bytes.Buffer{} + for name, ident := range state.Identities.ByName { + if _, err := fmt.Fprintf(buf, "%s:\n", name); err != nil { + return err + } + + for domain, id := range state.Identities.ByDomain { + if id == ident { + if _, err := fmt.Fprintf(buf, " domain %s\n", domain); err != nil { + return err + } + } + } + for folder, id := range state.Identities.ByFolder { + if id == ident { + if _, err := fmt.Fprintf(buf, " folder %s\n", folder); err != nil { + return err + } + } + } + for page, id := range state.Identities.ByPage { + if id == ident { + if _, err := fmt.Fprintf(buf, " page %s\n", page); err != nil { + return err + } + } + } + } + + _, err := io.Copy(os.Stdout, buf) + return err +} + +func IdentityDelete(state *BrowserState, name string) error { + name, err := findIdentity(state, name) + if err != nil { + return err + } + + ident := state.Identities.ByName[name] + delete(state.Identities.ByName, name) + + for domain, id := range state.Identities.ByDomain { + if id == ident { + delete(state.Identities.ByDomain, domain) + } + } + for folder, id := range state.Identities.ByFolder { + if id == ident { + delete(state.Identities.ByFolder, folder) + } + } + for page, id := range state.Identities.ByPage { + if id == ident { + delete(state.Identities.ByPage, page) + } + } + + if err := removeIdentity(name); err != nil { + return err + } + return saveIdentities(state.Identities) +} + +func IdentityUseDomain(state *BrowserState, name string, domain string) error { + name, err := findIdentity(state, name) + if err != nil { + return err + } + ident := state.Identities.ByName[name] + + u, _, err := parseURL(domain, state, "gemini") + if errors.Is(err, ErrInvalidLink) { + u, err = url.Parse(domain) + if err != nil { + return ErrInvalidLink + } + if u.Hostname() == "" { + u.Host = domain + } + } else if err != nil { + return err + } + + state.Identities.ByDomain[u.Hostname()] = ident + return saveIdentities(state.Identities) +} + +func IdentityUseFolder(state *BrowserState, name string, domain string) error { + name, err := findIdentity(state, name) + if err != nil { + return err + } + ident := state.Identities.ByName[name] + + u, _, err := parseURL(domain, state, "gemini") + if errors.Is(err, ErrInvalidLink) { + u, err = url.Parse(domain) + if err != nil { + return ErrInvalidLink + } + if u.Hostname() == "" { + u.Host = domain + } + } else if err != nil { + return err + } + + state.Identities.ByFolder[fmt.Sprintf("%s/%s", u.Hostname(), u.Path)] = ident + return saveIdentities(state.Identities) +} + +func IdentityUsePage(state *BrowserState, name string, domain string) error { + name, err := findIdentity(state, name) + if err != nil { + return err + } + ident := state.Identities.ByName[name] + + u, _, err := parseURL(domain, state, "gemini") + if errors.Is(err, ErrInvalidLink) { + u, err = url.Parse(domain) + if err != nil { + return ErrInvalidLink + } + if u.Hostname() == "" { + u.Host = domain + } + } else if err != nil { + return err + } + + state.Identities.ByPage[u.String()] = ident + return saveIdentities(state.Identities) +} |
