Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
Zach Abrahamson committed Jul 18, 2016
1 parent ce262c9 commit 837855f
Show file tree
Hide file tree
Showing 4 changed files with 319 additions and 0 deletions.
132 changes: 132 additions & 0 deletions box.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package box

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strconv"
"time"

"github.com/dgrijalva/jwt-go"
)

type Config struct {
Client ClientConfig `json:"client"`
Events EventsConfig `json:"events"`
}

type ClientConfig struct {
Token string `json:"token"`
UrlBase string `json:"url_base"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
JWTCustomClaims JWTCustomClaims `json:"jwt_custom_claims"`
}

type EventsConfig struct {
StartTime string `json:"start_time"`
EventLimit string `json:"event_limit"`
}

type JWTCustomClaims struct {
Iss string `json:"iss"`
Sub string `json:"sub"`
SubType string `json:"box_sub_type"`
Aud string `json:"aud"`
Jti string `json:"jti"`
Exp int64 `json:"exp"`
KeyID string `json:"key_id"`
jwt.StandardClaims
}

type Client struct {
HttpClient *http.Client
BaseUrl *url.URL
Token string
}

func NewClient(tok string, urlBase string) *Client {
baseURL, _ := url.Parse(urlBase)
return &Client{
HttpClient: &http.Client{},
BaseUrl: baseURL,
Token: tok,
}
}

func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) {
_, err := url.Parse(urlStr)
if err != nil {
return nil, err
}

resolvedUrl, err := url.Parse(c.BaseUrl.String() + urlStr)
if err != nil {
return nil, err
}
buf := new(bytes.Buffer)
if body != nil {
if err = json.NewEncoder(buf).Encode(body); err != nil {
return nil, err
}
}

req, err := http.NewRequest(method, resolvedUrl.String(), buf)
if err != nil {
return nil, err
}

return req, nil
}

func (c *Client) Do(req *http.Request, respStr interface{}) (*http.Response, error) {
resp, err := c.HttpClient.Do(req)
if err != nil {
//fmt.Printf("box client.Do error: %s\n", err)
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode > 299 || resp.StatusCode < 200 {
if resp.StatusCode == 429 {
retrySecs, _ := strconv.Atoi(resp.Header.Get("Retry-after"))
time.Sleep(time.Duration(retrySecs) * time.Second)
return nil, fmt.Errorf("rate limited for %d seconds", retrySecs)
} else {
return nil, fmt.Errorf("http request failed, resp: %#v", resp)
}
}

if respStr != nil {
err = json.NewDecoder(resp.Body).Decode(respStr)
}
return resp, err
}

func (c *Client) DoWithRetries(req *http.Request, respStr interface{}, retries int) (*http.Response, error) {
var resp http.Response
for i := 0; i < retries; i++ {
resp, err := c.Do(req, respStr)
if err != nil {
if i >= retries {
return nil, fmt.Errorf("http request failed, resp: %#v", resp)
}
continue
}
}
return &resp, nil
}

func (c *Client) EventService() *EventService {
return &EventService{
Client: c,
}
}

func (c *Client) FileService() *FileService {
return &FileService{
Client: c,
}
}
16 changes: 16 additions & 0 deletions common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package box

type User struct {
Type string `json:"type"`
ID string `json:"id"`
Name string `json:"name"`
Login string `json:"login"`
}

type ItemParent struct {
Type string `json:"type"`
ID string `json:"id"`
SequenceID string `json:"sequence_id"`
Etag string `json:"etag"`
Name string `json:"name"`
}
88 changes: 88 additions & 0 deletions events.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package box

import (
"fmt"
"net/http"
)

type EventService struct {
*Client
}

type EventDetails struct {
ServiceID string `json:"service_id"`
EkmID string `json:"ekm_id"`
VersionID string `json:"version_id"`
ServiceName string `json:"service_name"`
}

type EventSource struct {
ItemID string `json:"item_id"`
ItemType string `json:"item_type"`
Parent *ItemParent `json:"parent"`
ItemName string `json:"item_name"`
}

type Event struct {
EventType string `json:"event_type"`
EventID string `json:"event_id"`
Type string `json:"type"`
CreatedAt string `json:"created_at"`
CreatedBy *User `json:"created_by"`
Source *EventSource `json:"source"`
SessionID interface{} `json:"session_id"`
AdditionalDetails *EventDetails `json:"additional_details"`
IPAddress string `json:"ip_address"`
}

type EventsCollection struct {
ChunkSize int `json:"chunk_size"`
NextStreamPosition string `json:"next_stream_position"`
Entries []*Event `json:"entries"`
}

func (e *EventService) getSeedStreamPos(startTime string) string {
var respBoxEventsJSON EventsCollection
req, err := http.NewRequest("GET", e.BaseUrl.String()+"/events?stream_type=admin_logs&limit=1&created_after="+startTime, nil)
req.Header.Add("Authorization", "Bearer "+e.Token)
_, err = e.DoWithRetries(req, &respBoxEventsJSON, 5)
if err != nil {
fmt.Println("this unmarshal")
fmt.Println(err)
}
return respBoxEventsJSON.NextStreamPosition
}

func (e *EventService) getEvents(eventLimit string, streamPos string) *EventsCollection {
var respBoxEventsJSON EventsCollection
req, err := http.NewRequest("GET", e.BaseUrl.String()+"/events?stream_type=admin_logs&limit="+eventLimit+"&stream_position="+streamPos, nil)
req.Header.Add("Authorization", "Bearer "+e.Token)
_, err = e.DoWithRetries(req, &respBoxEventsJSON, 5)
if err != nil {

fmt.Println(err)
}
return &respBoxEventsJSON
}

func (e *EventService) streamEvents(eventLimit string, streamPos string, tunnel chan *Event) {
for {
if streamPos == "" {
close(tunnel)
return
}
eventsCollection := e.getEvents(eventLimit, streamPos)
for _, event := range eventsCollection.Entries {
tunnel <- event
}
streamPos = eventsCollection.NextStreamPosition
//time.Sleep(2 * time.Second)
}
}

func (e *EventService) Channel(eventLimit string, startTime string) chan *Event {
streamPos := e.getSeedStreamPos(startTime)
eventStream := make(chan *Event)
go e.streamEvents(eventLimit, streamPos, eventStream)
return eventStream
}
83 changes: 83 additions & 0 deletions file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package box

import "net/http"

type FileService struct {
*Client
}

type FileVersion struct {
Type string `json:"type"`
ID string `json:"id"`
Sha1 string `json:"sha1"`
}

type FileEntry struct {
Type string `json:"type"`
ID string `json:"id"`
SequenceID interface{} `json:"sequence_id"`
Etag interface{} `json:"etag"`
Name string `json:"name"`
}

type FilePathCollection struct {
TotalCount int `json:"total_count"`
Entries *[]FileEntry `json:"entries"`
}

type SharedLinkPermissions struct {
CanDownload bool `json:"can_download"`
CanPreview bool `json:"can_preview"`
}

type SharedLink struct {
URL string `json:"url"`
DownloadURL string `json:"download_url"`
VanityURL interface{} `json:"vanity_url"`
IsPasswordEnabled bool `json:"is_password_enabled"`
UnsharedAt interface{} `json:"unshared_at"`
DownloadCount int `json:"download_count"`
PreviewCount int `json:"preview_count"`
Access string `json:"access"`
Permissions *SharedLinkPermissions `json:"permissions"`
}

type FileParent struct {
Type string `json:"type"`
ID string `json:"id"`
SequenceID string `json:"sequence_id"`
Etag string `json:"etag"`
Name string `json:"name"`
}

type File struct {
Type string `json:"type"`
ID string `json:"id"`
FileVersion *FileVersion `json:"file_version"`
SequenceID string `json:"sequence_id"`
Etag string `json:"etag"`
Sha1 string `json:"sha1"`
Name string `json:"name"`
Description string `json:"description"`
Size int `json:"size"`
PathCollection *FilePathCollection `json:"path_collection"`
CreatedAt string `json:"created_at"`
ModifiedAt string `json:"modified_at"`
CreatedBy *User `json:"created_by"`
ModifiedBy *User `json:"modified_by"`
OwnedBy *User `json:"owned_by"`
SharedLink *SharedLink `json:"shared_link"`
Parent *ItemParent `json:"parent"`
ItemStatus string `json:"item_status"`
}

func (f *FileService) GetFileHash(fileID string) (string, error) {
var respFileJSON File
req, err := http.NewRequest("GET", f.BaseUrl.String()+"/files/"+fileID, nil)
req.Header.Add("Authorization", "Bearer "+f.Token)
_, err = f.Do(req, &respFileJSON)
if err != nil {
return "", err
}
return respFileJSON.Sha1, nil
}

0 comments on commit 837855f

Please sign in to comment.