Initial commit
This commit is contained in:
commit
ad529187f5
13 changed files with 909 additions and 0 deletions
6
.dependabot/config.yml
Normal file
6
.dependabot/config.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
version: 1
|
||||
|
||||
update_configs:
|
||||
- package_manager: "go:modules"
|
||||
directory: "/"
|
||||
update_schedule: "daily"
|
16
.github/workflows/main.yml
vendored
Normal file
16
.github/workflows/main.yml
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
name: Test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install dependencies
|
||||
run: go get
|
||||
|
||||
- name: Run tests
|
||||
run: go test -v ./...
|
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Editors related
|
||||
.vscode
|
||||
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2020 Sighery
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
54
README.md
Normal file
54
README.md
Normal file
|
@ -0,0 +1,54 @@
|
|||
# Unofficial Golang library for the Njalla API
|
||||
|
||||
[Njalla][] is a privacy-oriented domain name registration service. Recently
|
||||
they released their [official API][].
|
||||
|
||||
This Golang library covers _some_ methods of that API. For the moment, those
|
||||
are:
|
||||
* `list-domains`
|
||||
* `get-domain`
|
||||
* `list-records`
|
||||
* `add-record`
|
||||
* `edit-record`
|
||||
* `remove-record`
|
||||
|
||||
**TO NOTE**: Even though `record` methods are implemented, I'm fairly certain
|
||||
they'll fail (silently or not) in some cases. I deal mostly with `TXT`, `MX`,
|
||||
`A` and `AAAA` DNS records. Some records have different/more variables, and
|
||||
since I don't use them I decided against implementing them. Chances are the
|
||||
methods will fail when trying to deal with those types of records (like `SSH`
|
||||
records).
|
||||
|
||||
The code is fairly simple, and all the methods are tested by using mocks on
|
||||
the API request. The mocked returned data is based on the same data the API
|
||||
returns.
|
||||
|
||||
These methods cover my needs, but feel free to send in a PR to add more (or to
|
||||
cover all types of DNS records), as long as they're all tested and documented.
|
||||
|
||||
### Usage
|
||||
|
||||
```golang
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Sighery/gonjalla"
|
||||
)
|
||||
|
||||
func main() {
|
||||
token := "api-token"
|
||||
domain := "your-domain"
|
||||
|
||||
records, err := ListRecords(token, domain)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
fmt.Println(records)
|
||||
}
|
||||
```
|
||||
|
||||
[Njalla]: https://njal.la
|
||||
[official API]: https://njal.la/api/
|
58
domains.go
Normal file
58
domains.go
Normal file
|
@ -0,0 +1,58 @@
|
|||
package gonjalla
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Domain struct contains data returned by `list-domains` and `get-domains`
|
||||
type Domain struct {
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
Expiry time.Time `json:"expiry"`
|
||||
Locked *bool `json:"locked,omitempty"`
|
||||
Mailforwarding *bool `json:"mailforwarding,omitempty"`
|
||||
MaxNameservers *int `json:"max_nameservers,omitempty"`
|
||||
}
|
||||
|
||||
// ListDomains returns a listing of domains with minimal data
|
||||
func ListDomains(token string) ([]Domain, error) {
|
||||
params := map[string]interface{}{}
|
||||
|
||||
data, err := Request(token, "list-domains", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Domains []Domain `json:"domains"`
|
||||
}
|
||||
|
||||
var response Response
|
||||
err = json.Unmarshal(data, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response.Domains, nil
|
||||
}
|
||||
|
||||
// GetDomain returns detailed information for each domain
|
||||
func GetDomain(token string, domain string) (Domain, error) {
|
||||
params := map[string]interface{}{
|
||||
"domain": domain,
|
||||
}
|
||||
|
||||
data, err := Request(token, "get-domain", params)
|
||||
if err != nil {
|
||||
return Domain{}, err
|
||||
}
|
||||
|
||||
var domainStruct Domain
|
||||
err = json.Unmarshal(data, &domainStruct)
|
||||
if err != nil {
|
||||
return Domain{}, err
|
||||
}
|
||||
|
||||
return domainStruct, nil
|
||||
}
|
163
domains_test.go
Normal file
163
domains_test.go
Normal file
|
@ -0,0 +1,163 @@
|
|||
package gonjalla
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/Sighery/gonjalla/mocks"
|
||||
)
|
||||
|
||||
func TestListDomainsExpected(t *testing.T) {
|
||||
token := "test-token"
|
||||
Client = &mocks.MockClient{}
|
||||
|
||||
testData := `{
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"domains": [
|
||||
{
|
||||
"name": "testing1.com",
|
||||
"status": "active",
|
||||
"expiry": "2021-02-20T19:38:48Z"
|
||||
},
|
||||
{
|
||||
"name": "testing2.com",
|
||||
"status": "inactive",
|
||||
"expiry": "2021-02-20T19:38:48Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
}`
|
||||
r := ioutil.NopCloser(bytes.NewReader([]byte(testData)))
|
||||
|
||||
mocks.GetDoFunc = func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
domains, err := ListDomains(token)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
expectedTime, _ := time.Parse(time.RFC3339, "2021-02-20T19:38:48Z")
|
||||
|
||||
expected := []Domain{
|
||||
{
|
||||
Name: "testing1.com",
|
||||
Status: "active",
|
||||
Expiry: expectedTime,
|
||||
},
|
||||
{
|
||||
Name: "testing2.com",
|
||||
Status: "inactive",
|
||||
Expiry: expectedTime,
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, domains, expected)
|
||||
}
|
||||
|
||||
func TestListDomainsError(t *testing.T) {
|
||||
token := "test-token"
|
||||
Client = &mocks.MockClient{}
|
||||
|
||||
testData := `{
|
||||
"jsonrpc": "2.0",
|
||||
"error": {
|
||||
"code": 0,
|
||||
"message": "Testing error"
|
||||
}
|
||||
}`
|
||||
r := ioutil.NopCloser(bytes.NewReader([]byte(testData)))
|
||||
|
||||
mocks.GetDoFunc = func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
domains, err := ListDomains(token)
|
||||
assert.Nil(t, domains)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestGetDomainExpected(t *testing.T) {
|
||||
token := "test-token"
|
||||
domain := "testing.com"
|
||||
Client = &mocks.MockClient{}
|
||||
|
||||
testData := `{
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"name": "testing.com",
|
||||
"status": "active",
|
||||
"expiry": "2021-02-20T19:38:48Z",
|
||||
"locked": true,
|
||||
"mailforwarding": false,
|
||||
"max_nameservers": 10
|
||||
}
|
||||
}`
|
||||
r := ioutil.NopCloser(bytes.NewReader([]byte(testData)))
|
||||
|
||||
mocks.GetDoFunc = func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
result, err := GetDomain(token, domain)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
expectedTime, _ := time.Parse(time.RFC3339, "2021-02-20T19:38:48Z")
|
||||
locked := true
|
||||
mailforwarding := false
|
||||
maxNameservers := 10
|
||||
|
||||
expected := Domain{
|
||||
Name: domain,
|
||||
Status: "active",
|
||||
Expiry: expectedTime,
|
||||
Locked: &locked,
|
||||
Mailforwarding: &mailforwarding,
|
||||
MaxNameservers: &maxNameservers,
|
||||
}
|
||||
|
||||
assert.Equal(t, result, expected)
|
||||
}
|
||||
|
||||
func TestGetDomainError(t *testing.T) {
|
||||
token := "test-token"
|
||||
domain := "testing.com"
|
||||
Client = &mocks.MockClient{}
|
||||
|
||||
testData := `{
|
||||
"jsonrpc": "2.0",
|
||||
"error": {
|
||||
"code": 0,
|
||||
"message": "Testing error"
|
||||
}
|
||||
}`
|
||||
r := ioutil.NopCloser(bytes.NewReader([]byte(testData)))
|
||||
|
||||
mocks.GetDoFunc = func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
_, err := GetDomain(token, domain)
|
||||
assert.Error(t, err)
|
||||
}
|
5
go.mod
Normal file
5
go.mod
Normal file
|
@ -0,0 +1,5 @@
|
|||
module github.com/Sighery/gonjalla
|
||||
|
||||
go 1.14
|
||||
|
||||
require github.com/stretchr/testify v1.5.1
|
11
go.sum
Normal file
11
go.sum
Normal file
|
@ -0,0 +1,11 @@
|
|||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
18
mocks/mocks.go
Normal file
18
mocks/mocks.go
Normal file
|
@ -0,0 +1,18 @@
|
|||
package mocks
|
||||
|
||||
import "net/http"
|
||||
|
||||
// MockClient is the mock HTTP client used for tests
|
||||
type MockClient struct {
|
||||
DoFunc func(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
var (
|
||||
// GetDoFunc fetches the mock client's `Do` func
|
||||
GetDoFunc func(req *http.Request) (*http.Response, error)
|
||||
)
|
||||
|
||||
// Do is the mock client's `Do` func
|
||||
func (m *MockClient) Do(req *http.Request) (*http.Response, error) {
|
||||
return GetDoFunc(req)
|
||||
}
|
86
provider.go
Normal file
86
provider.go
Normal file
|
@ -0,0 +1,86 @@
|
|||
package gonjalla
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type request struct {
|
||||
Method string `json:"method"`
|
||||
Params map[string]interface{} `json:"params"`
|
||||
}
|
||||
|
||||
const endpoint string = "https://njal.la/api/1/"
|
||||
|
||||
// HTTPClient interface. Useful for mocked unit tests later on.
|
||||
type HTTPClient interface {
|
||||
Do(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
var (
|
||||
// Client used in all requests by Request. Can be overwritten for tests.
|
||||
Client HTTPClient
|
||||
)
|
||||
|
||||
func init() {
|
||||
Client = &http.Client{}
|
||||
}
|
||||
|
||||
// Request common function for all of Njalla's API.
|
||||
// Njalla's API uses JSON-RPC, and contains just one endpoint.
|
||||
// The endpoint is POST only, and takes in a JSON in the body, with two
|
||||
// arguments, check the `request` struct for more info.
|
||||
// The `params` argument is variable. Some methods require no parameters,
|
||||
// (like `list-domains`), while other methods require parameters (like
|
||||
// `get-domain` which requires `domain: string`).
|
||||
func Request(
|
||||
token string, method string, params map[string]interface{},
|
||||
) ([]byte, error) {
|
||||
token = fmt.Sprintf("Njalla %s", token)
|
||||
|
||||
body, err := json.Marshal(
|
||||
request{Method: method, Params: params},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Add("Authorization", token)
|
||||
|
||||
resp, err := Client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
jsonData, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := make(map[string]interface{})
|
||||
|
||||
err = json.Unmarshal(jsonData, &data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result, ok := data["result"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Missing result %s", data)
|
||||
}
|
||||
|
||||
unwrapped, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return unwrapped, nil
|
||||
}
|
111
records.go
Normal file
111
records.go
Normal file
|
@ -0,0 +1,111 @@
|
|||
package gonjalla
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
// Record struct contains data returned by `list-records`
|
||||
type Record struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Content string `json:"content"`
|
||||
TTL int `json:"ttl"`
|
||||
Priority *int `json:"prio,omitempty"`
|
||||
}
|
||||
|
||||
// ListRecords returns a listing of all records for a given domain
|
||||
func ListRecords(token string, domain string) ([]Record, error) {
|
||||
params := map[string]interface{}{
|
||||
"domain": domain,
|
||||
}
|
||||
data, err := Request(token, "list-records", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Records []Record `json:"records"`
|
||||
}
|
||||
|
||||
var response Response
|
||||
err = json.Unmarshal(data, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response.Records, nil
|
||||
}
|
||||
|
||||
// AddRecord adds a given record to a given domain.
|
||||
// Returns a new Record struct, containing the response from the API if
|
||||
// successful. This response will have some fields like ID (which can only
|
||||
// be known after the execution) filled.
|
||||
func AddRecord(token string, domain string, record Record) (Record, error) {
|
||||
marshal, err := json.Marshal(record)
|
||||
if err != nil {
|
||||
return Record{}, err
|
||||
}
|
||||
|
||||
params := map[string]interface{}{
|
||||
"domain": domain,
|
||||
}
|
||||
err = json.Unmarshal(marshal, ¶ms)
|
||||
if err != nil {
|
||||
return Record{}, err
|
||||
}
|
||||
|
||||
data, err := Request(token, "add-record", params)
|
||||
if err != nil {
|
||||
return Record{}, err
|
||||
}
|
||||
|
||||
var response Record
|
||||
err = json.Unmarshal(data, &response)
|
||||
if err != nil {
|
||||
return Record{}, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// RemoveRecord removes a given record from a given domain.
|
||||
// If there are no errors it will return `nil`.
|
||||
func RemoveRecord(token string, domain string, id int) error {
|
||||
params := map[string]interface{}{
|
||||
"domain": domain,
|
||||
"id": id,
|
||||
}
|
||||
|
||||
_, err := Request(token, "remove-record", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EditRecord edits a record for a given domain.
|
||||
// This function is fairly dumb. It takes in a `Record` struct, and uses all
|
||||
// its filled fields to send to Njalla.
|
||||
// So, if you want to only change a given field, get the `Record` object from
|
||||
// say ListRecords, change the one field you want, and then pass that here.
|
||||
func EditRecord(token string, domain string, record Record) error {
|
||||
marshal, err := json.Marshal(record)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
params := map[string]interface{}{
|
||||
"domain": domain,
|
||||
}
|
||||
err = json.Unmarshal(marshal, ¶ms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = Request(token, "edit-record", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
342
records_test.go
Normal file
342
records_test.go
Normal file
|
@ -0,0 +1,342 @@
|
|||
package gonjalla
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/Sighery/gonjalla/mocks"
|
||||
)
|
||||
|
||||
func TestListRecordsExpected(t *testing.T) {
|
||||
token := "test-token"
|
||||
domain := "testing.com"
|
||||
Client = &mocks.MockClient{}
|
||||
|
||||
testData := `{
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"records": [
|
||||
{
|
||||
"id": 1337,
|
||||
"name": "_acme-challenge",
|
||||
"type": "TXT",
|
||||
"content": "long-string",
|
||||
"ttl": 10800
|
||||
},
|
||||
{
|
||||
"id": 1338,
|
||||
"name": "@",
|
||||
"type": "A",
|
||||
"content": "1.2.3.4",
|
||||
"ttl": 3600
|
||||
},
|
||||
{
|
||||
"id": 1339,
|
||||
"name": "@",
|
||||
"type": "AAAA",
|
||||
"content": "2001:0DB8:0000:0000:0000:8A2E:0370:7334",
|
||||
"ttl": 900
|
||||
},
|
||||
{
|
||||
"id": 1340,
|
||||
"name": "@",
|
||||
"type": "MX",
|
||||
"content": "mail.protonmail.ch",
|
||||
"ttl": 300,
|
||||
"prio": 10
|
||||
}
|
||||
]
|
||||
}
|
||||
}`
|
||||
r := ioutil.NopCloser(bytes.NewReader([]byte(testData)))
|
||||
|
||||
mocks.GetDoFunc = func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
records, err := ListRecords(token, domain)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
priority := 10
|
||||
|
||||
expected := []Record{
|
||||
{
|
||||
ID: 1337,
|
||||
Name: "_acme-challenge",
|
||||
Type: "TXT",
|
||||
Content: "long-string",
|
||||
TTL: 10800,
|
||||
},
|
||||
{
|
||||
ID: 1338,
|
||||
Name: "@",
|
||||
Type: "A",
|
||||
Content: "1.2.3.4",
|
||||
TTL: 3600,
|
||||
},
|
||||
{
|
||||
ID: 1339,
|
||||
Name: "@",
|
||||
Type: "AAAA",
|
||||
Content: "2001:0DB8:0000:0000:0000:8A2E:0370:7334",
|
||||
TTL: 900,
|
||||
},
|
||||
{
|
||||
ID: 1340,
|
||||
Name: "@",
|
||||
Type: "MX",
|
||||
Content: "mail.protonmail.ch",
|
||||
TTL: 300,
|
||||
Priority: &priority,
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, records, expected)
|
||||
}
|
||||
|
||||
func TestListRecordsError(t *testing.T) {
|
||||
token := "test-token"
|
||||
domain := "testing.com"
|
||||
Client = &mocks.MockClient{}
|
||||
|
||||
testData := `{
|
||||
"jsonrpc": "2.0",
|
||||
"error": {
|
||||
"code": 0,
|
||||
"message": "Testing error"
|
||||
}
|
||||
}`
|
||||
r := ioutil.NopCloser(bytes.NewReader([]byte(testData)))
|
||||
|
||||
mocks.GetDoFunc = func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
records, err := ListRecords(token, domain)
|
||||
if records != nil {
|
||||
t.Error("records isn't nil")
|
||||
}
|
||||
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestAddRecordExpected(t *testing.T) {
|
||||
token := "test-token"
|
||||
domain := "testing.com"
|
||||
Client = &mocks.MockClient{}
|
||||
|
||||
testData := `{
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"id": 1337,
|
||||
"name": "@",
|
||||
"type": "MX",
|
||||
"content": "testing.com",
|
||||
"ttl": 10800,
|
||||
"prio": 10
|
||||
}
|
||||
}`
|
||||
r := ioutil.NopCloser(bytes.NewReader([]byte(testData)))
|
||||
|
||||
mocks.GetDoFunc = func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
priority := 10
|
||||
|
||||
adding := Record{
|
||||
Name: "@",
|
||||
Type: "MX",
|
||||
Content: "testing.com",
|
||||
TTL: 10800,
|
||||
Priority: &priority,
|
||||
}
|
||||
|
||||
record, err := AddRecord(token, domain, adding)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
expected := Record{
|
||||
ID: 1337,
|
||||
Name: "@",
|
||||
Type: "MX",
|
||||
Content: "testing.com",
|
||||
TTL: 10800,
|
||||
Priority: &priority,
|
||||
}
|
||||
|
||||
assert.Equal(t, record, expected)
|
||||
}
|
||||
|
||||
func TestAddRecordError(t *testing.T) {
|
||||
token := "test-token"
|
||||
domain := "testing.com"
|
||||
Client = &mocks.MockClient{}
|
||||
|
||||
testData := `{
|
||||
"jsonrpc": "2.0",
|
||||
"error": {
|
||||
"code": 0,
|
||||
"message": "Testing error"
|
||||
}
|
||||
}`
|
||||
r := ioutil.NopCloser(bytes.NewReader([]byte(testData)))
|
||||
|
||||
mocks.GetDoFunc = func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
priority := 10
|
||||
adding := Record{
|
||||
Name: "@",
|
||||
Type: "MX",
|
||||
Content: "testing.com",
|
||||
TTL: 10800,
|
||||
Priority: &priority,
|
||||
}
|
||||
|
||||
_, err := AddRecord(token, domain, adding)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestRemoveRecordExpected(t *testing.T) {
|
||||
token := "test-token"
|
||||
domain := "testing.com"
|
||||
id := 1337
|
||||
Client = &mocks.MockClient{}
|
||||
|
||||
testData := `{
|
||||
"jsonrpc": "2.0",
|
||||
"result": {}
|
||||
}`
|
||||
r := ioutil.NopCloser(bytes.NewReader([]byte(testData)))
|
||||
|
||||
mocks.GetDoFunc = func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
err := RemoveRecord(token, domain, id)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestRemoveRecordError(t *testing.T) {
|
||||
token := "test-token"
|
||||
domain := "testing.com"
|
||||
id := 1337
|
||||
Client = &mocks.MockClient{}
|
||||
|
||||
testData := `{
|
||||
"jsonrpc": "2.0",
|
||||
"error": {
|
||||
"code": 0,
|
||||
"message": "Testing error"
|
||||
}
|
||||
}`
|
||||
r := ioutil.NopCloser(bytes.NewReader([]byte(testData)))
|
||||
|
||||
mocks.GetDoFunc = func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
err := RemoveRecord(token, domain, id)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestEditRecordExpected(t *testing.T) {
|
||||
token := "test-token"
|
||||
domain := "testing.com"
|
||||
Client = &mocks.MockClient{}
|
||||
|
||||
testData := `{
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"id": 1337,
|
||||
"name": "@",
|
||||
"type": "MX",
|
||||
"content": "testing.com",
|
||||
"ttl": 10800,
|
||||
"prio": 10
|
||||
}
|
||||
}`
|
||||
r := ioutil.NopCloser(bytes.NewReader([]byte(testData)))
|
||||
|
||||
mocks.GetDoFunc = func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
priority := 10
|
||||
editing := Record{
|
||||
ID: 1337,
|
||||
Name: "@",
|
||||
Type: "MX",
|
||||
Content: "testing.com",
|
||||
TTL: 10800,
|
||||
Priority: &priority,
|
||||
}
|
||||
|
||||
err := EditRecord(token, domain, editing)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestEditRecordError(t *testing.T) {
|
||||
token := "test-token"
|
||||
domain := "testing.com"
|
||||
Client = &mocks.MockClient{}
|
||||
|
||||
testData := `{
|
||||
"jsonrpc": "2.0",
|
||||
"error": {
|
||||
"code": 0,
|
||||
"message": "Testing error"
|
||||
}
|
||||
}`
|
||||
r := ioutil.NopCloser(bytes.NewReader([]byte(testData)))
|
||||
|
||||
mocks.GetDoFunc = func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
priority := 10
|
||||
editing := Record{
|
||||
ID: 1337,
|
||||
Name: "@",
|
||||
Type: "MX",
|
||||
Content: "testing.com",
|
||||
TTL: 10800,
|
||||
Priority: &priority,
|
||||
}
|
||||
|
||||
err := EditRecord(token, domain, editing)
|
||||
assert.Error(t, err)
|
||||
}
|
Loading…
Reference in a new issue