package client import ( "bytes" "encoding/json" "errors" "fmt" "io/ioutil" "net/http" "net/url" "strconv" "git.andreafazzi.eu/andrea/oef/orm" "git.andreafazzi.eu/andrea/oef/reflect" "git.andreafazzi.eu/andrea/oef/renderer" "github.com/jinzhu/gorm" ) // A client represents a client connection to the Headmaster test // server. type Client struct { Url *url.URL Username string Password string User string token string } // Dial connects to a test server instance at the specified address // using the given credentials. func Dial(host, username, password string) (*Client, error) { url, err := url.Parse(host) if err != nil { return nil, err } client := &Client{ Url: url, Username: username, Password: password, } response, err := client.SendRequest("GET", "get_token", nil) if err != nil { panic(err) } var data struct { Token string User string } if err := json.Unmarshal(response, &data); err != nil { return nil, err } client.token = data.Token client.User = data.User return client, nil } // GetToken get the token associated with the user. func GetToken(host, username, password string) (string, error) { client, err := Dial(host, username, password) if err != nil { return "", err } return client.token, err } func (c *Client) SendRequest(method string, path string, data []byte) ([]byte, error) { // Create the https request folderUrl, err := url.Parse(path) if err != nil { return nil, err } client := &http.Client{} req, err := http.NewRequest(method, c.Url.ResolveReference(folderUrl).String(), bytes.NewReader(data)) if err != nil { return nil, err } req.Header.Set("Content-Type", "application/json") req.SetBasicAuth(c.Username, c.Password) if c.token != "" { req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.token)) } resp, err := client.Do(req) if err != nil { return nil, err } body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } return body, nil } func (c *Client) ReadAll(model interface{}) error { var response renderer.JsonResponse data, err := c.SendRequest("GET", fmt.Sprintf("/api/%s?format=json", reflect.ModelNameLowerPlural(model)), nil) if err != nil { return err } if err := json.Unmarshal(data, &response); err != nil { return err } if string(response.Error) != "" { return errors.New(string(response.Error)) } if err := json.Unmarshal(response.Result, &model); err != nil { return err } return nil } func (c *Client) Read(model orm.IDer) (interface{}, error) { var response renderer.JsonResponse data, err := c.SendRequest("GET", fmt.Sprintf("/api/%s/%d?format=json", reflect.ModelNameLowerPlural(model), model.GetID()), nil) if err != nil { return nil, err } if err := json.Unmarshal(data, &response); err != nil { return nil, err } if string(response.Error) != "" { return nil, errors.New(string(response.Error)) } if err := json.Unmarshal(response.Result, &model); err != nil { return nil, err } return data, nil } func (c *Client) Create(model interface{}) (uint, error) { var response renderer.JsonResponse data, err := json.Marshal(model) if err != nil { return 0, err } resp, err := c.SendRequest("POST", fmt.Sprintf("/api/%s/create/?format=json", reflect.ModelNameLowerPlural(model)), data) if err != nil { return 0, err } if err := json.Unmarshal(resp, &response); err != nil { return 0, err } if string(response.Error) != "" { return 0, errors.New(string(response.Error)) } id, err := strconv.Atoi(string(response.Result)) if err != nil { return 0, err } return uint(id), nil } func (c *Client) Update(model orm.IDer) (uint, error) { var response renderer.JsonResponse data, err := json.Marshal(model) if err != nil { return 0, err } resp, err := c.SendRequest("POST", fmt.Sprintf("/api/%s/%d/update?format=json", reflect.ModelNameLowerPlural(model), model.GetID()), data) if err != nil { return 0, err } if err := json.Unmarshal(resp, &response); err != nil { return 0, err } if string(response.Error) != "" { return 0, errors.New(string(response.Error)) } id, err := strconv.Atoi(string(response.Result)) if err != nil { return 0, err } return uint(id), nil } func (c *Client) Delete(model orm.IDer) (uint, error) { var response renderer.JsonResponse data, err := json.Marshal(model) if err != nil { return 0, err } resp, err := c.SendRequest("DELETE", fmt.Sprintf("/api/%s/%d/delete?format=json", reflect.ModelNameLowerPlural(model), model.GetID()), data) if err != nil { return 0, err } if err := json.Unmarshal(resp, &response); err != nil { return 0, err } if string(response.Error) != "" { return 0, errors.New(string(response.Error)) } id, err := strconv.Atoi(string(response.Result)) if err != nil { return 0, err } return uint(id), nil } // func (c *Client) DeleteAllFunc(model interface{}, testFn func(interface{}) bool) error { // err := c.ReadAll(model) // if err != nil { // return err // } // switch reflect.TypeOf(model).Kind() { // case reflect.Ptr: // s := reflect.ValueOf(model).Elem() // // FIXME: Check whatever s is a slice before cycling through it! // for i := 0; i < s.Len(); i++ { // // if callString(s.Index(i).Interface()) == name { // // _, err := c.Delete(s.Index(i).Interface().(orm.IDer)) // // if err != nil { // // return err // // } // // } // if testFn(s.Index(i).Interface()) { // _, err := c.Delete(s.Index(i).Interface().(orm.IDer)) // if err != nil { // return err // } // } // } // } // return nil // } func (c *Client) Exists(model orm.IDer) bool { _, err := c.Read(model) return err != gorm.ErrRecordNotFound }