mirror of
https://github.com/wneessen/go-hibp.git
synced 2024-11-23 05:10:50 +01:00
Road to v1.0.0: Added Pastes API
This commit is contained in:
parent
7da9c54633
commit
18c11d013a
5 changed files with 147 additions and 2 deletions
22
examples/breaches-api/breached-account/main.go
Normal file
22
examples/breaches-api/breached-account/main.go
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/wneessen/go-hibp"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
apiKey := os.Getenv("HIBP_API_KEY")
|
||||||
|
if apiKey == "" {
|
||||||
|
panic("A API key is required for this API")
|
||||||
|
}
|
||||||
|
hc := hibp.New(hibp.WithApiKey(apiKey))
|
||||||
|
bd, _, err := hc.BreachApi.BreachedAccount("multiple-breaches@hibp-integration-tests.com")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, b := range bd {
|
||||||
|
fmt.Printf("Your account was part of the %q breach\n", b.Name)
|
||||||
|
}
|
||||||
|
}
|
22
examples/pastes-api/pasted-account/main.go
Normal file
22
examples/pastes-api/pasted-account/main.go
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/wneessen/go-hibp"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
apiKey := os.Getenv("HIBP_API_KEY")
|
||||||
|
if apiKey == "" {
|
||||||
|
panic("A API key is required for this API")
|
||||||
|
}
|
||||||
|
hc := hibp.New(hibp.WithApiKey(apiKey))
|
||||||
|
pd, _, err := hc.PasteApi.PastedAccount("account-exists@hibp-integration-tests.com")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, p := range pd {
|
||||||
|
fmt.Printf("Your account was part of the %q paste\n", p.Title)
|
||||||
|
}
|
||||||
|
}
|
6
hibp.go
6
hibp.go
|
@ -12,7 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version represents the version of this package
|
// Version represents the version of this package
|
||||||
const Version = "0.1.5"
|
const Version = "1.0.0"
|
||||||
|
|
||||||
// BaseUrl is the base URL for the majority of API calls
|
// BaseUrl is the base URL for the majority of API calls
|
||||||
const BaseUrl = "https://haveibeenpwned.com/api/v3"
|
const BaseUrl = "https://haveibeenpwned.com/api/v3"
|
||||||
|
@ -36,7 +36,8 @@ type Client struct {
|
||||||
PwnedPassApi *PwnedPassApi // Reference to the PwnedPassApi API
|
PwnedPassApi *PwnedPassApi // Reference to the PwnedPassApi API
|
||||||
PwnedPassApiOpts *PwnedPasswordOptions // Additional options for the PwnedPassApi API
|
PwnedPassApiOpts *PwnedPasswordOptions // Additional options for the PwnedPassApi API
|
||||||
|
|
||||||
BreachApi *BreachApi // Reference to the BreachApi API
|
BreachApi *BreachApi // Reference to the BreachApi
|
||||||
|
PasteApi *PasteApi // Reference to the PasteApi
|
||||||
}
|
}
|
||||||
|
|
||||||
// Option is a function that is used for grouping of Client options.
|
// Option is a function that is used for grouping of Client options.
|
||||||
|
@ -65,6 +66,7 @@ func New(options ...Option) Client {
|
||||||
// Associate the different HIBP service APIs with the Client
|
// Associate the different HIBP service APIs with the Client
|
||||||
c.PwnedPassApi = &PwnedPassApi{hibp: &c}
|
c.PwnedPassApi = &PwnedPassApi{hibp: &c}
|
||||||
c.BreachApi = &BreachApi{hibp: &c}
|
c.BreachApi = &BreachApi{hibp: &c}
|
||||||
|
c.PasteApi = &PasteApi{hibp: &c}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
56
paste.go
Normal file
56
paste.go
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
package hibp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PasteApi is a HIBP pastes API client
|
||||||
|
type PasteApi struct {
|
||||||
|
hibp *Client // References back to the parent HIBP client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paste represents a JSON response structure of the pastes API
|
||||||
|
type Paste struct {
|
||||||
|
// Source is the paste service the record was retrieved from. Current values are: Pastebin,
|
||||||
|
// Pastie, Slexy, Ghostbin, QuickLeak, JustPaste, AdHocUrl, PermanentOptOut, OptOut
|
||||||
|
Source string `json:"Source"`
|
||||||
|
|
||||||
|
// Id of the paste as it was given at the source service. Combined with the "Source" attribute, this
|
||||||
|
// can be used to resolve the URL of the paste
|
||||||
|
Id string `json:"Id"`
|
||||||
|
|
||||||
|
// Title of the paste as observed on the source site. This may be null and if so will be omitted from
|
||||||
|
// the response
|
||||||
|
Title string `json:"Title"`
|
||||||
|
|
||||||
|
// Date is the date and time (precision to the second) that the paste was posted. This is taken directly
|
||||||
|
// from the paste site when this information is available but may be null if no date is published
|
||||||
|
Date time.Time `json:"Date"`
|
||||||
|
|
||||||
|
// EmailCount is number of emails that were found when processing the paste. Emails are extracted by
|
||||||
|
// using the regular expression \b[a-zA-Z0-9\.\-_\+]+@[a-zA-Z0-9\.\-_]+\.[a-zA-Z]+\b
|
||||||
|
EmailCount int `json:"EmailCount"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PastedAccount returns a single breached site based on its name
|
||||||
|
func (p *PasteApi) PastedAccount(a string) ([]*Paste, *http.Response, error) {
|
||||||
|
if a == "" {
|
||||||
|
return nil, nil, fmt.Errorf("no account id given")
|
||||||
|
}
|
||||||
|
|
||||||
|
apiUrl := fmt.Sprintf("%s/pasteaccount/%s", BaseUrl, a)
|
||||||
|
hb, hr, err := p.hibp.HttpResBody(http.MethodGet, apiUrl, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var pasteDetails []*Paste
|
||||||
|
if err := json.Unmarshal(hb, &pasteDetails); err != nil {
|
||||||
|
return nil, hr, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pasteDetails, hr, nil
|
||||||
|
}
|
43
paste_test.go
Normal file
43
paste_test.go
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package hibp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestPasteAccount tests the BreachedAccount() method of the breaches API
|
||||||
|
func TestPasteAccount(t *testing.T) {
|
||||||
|
testTable := []struct {
|
||||||
|
testName string
|
||||||
|
accountName string
|
||||||
|
isBreached bool
|
||||||
|
}{
|
||||||
|
{"account-exists is breached once", "account-exists", true},
|
||||||
|
{"opt-out is not breached", "opt-out", false},
|
||||||
|
}
|
||||||
|
|
||||||
|
apiKey := os.Getenv("HIBP_API_KEY")
|
||||||
|
if apiKey == "" {
|
||||||
|
t.SkipNow()
|
||||||
|
}
|
||||||
|
hc := New(WithApiKey(apiKey))
|
||||||
|
for _, tc := range testTable {
|
||||||
|
t.Run(tc.testName, func(t *testing.T) {
|
||||||
|
pasteDetails, _, err := hc.PasteApi.PastedAccount(
|
||||||
|
fmt.Sprintf("%s@hibp-integration-tests.com", tc.accountName))
|
||||||
|
if err != nil && tc.isBreached {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pasteDetails == nil && tc.isBreached {
|
||||||
|
t.Errorf("breach for the account %q is expected, but returned 0 results.",
|
||||||
|
tc.accountName)
|
||||||
|
}
|
||||||
|
if pasteDetails != nil && !tc.isBreached {
|
||||||
|
t.Errorf("breach for the account %q is expected to be not breached, but returned breach details.",
|
||||||
|
tc.accountName)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue