diff --git a/api/apiauth.go b/api/apiauth.go new file mode 100644 index 0000000..e4fb8f9 --- /dev/null +++ b/api/apiauth.go @@ -0,0 +1,53 @@ +package api + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "strings" +) + +// ---------------------------------------------- +// stucts +// ---------------------------------------------- + +type AuthResponse struct { + AccessToken string `json:"access_token"` + ExpiresIn int `json:"expires_in"` + TokenType string `json:"token_type"` + Scope string `json:"scope"` + RefreshToken string `json:"refresh_token"` + ErrorDescription string `json:"error_description"` +} + +// ---------------------------------------------- +// exported funtions +// ---------------------------------------------- + +func Authenticate(sitename, username, password string) (*AuthResponse, error) { + client := &http.Client{} + authReq := getAuthRequest(sitename) + authReq.Body = io.NopCloser(strings.NewReader(fmt.Sprintf("username=%s&password=%s&client_id=er_mobile_tracker&grant_type=password", username, password))) + + res, err := client.Do(&authReq) + if err != nil { + fmt.Println("Error making request:", err) + } + defer res.Body.Close() + + var responseData AuthResponse + err = json.NewDecoder(res.Body).Decode(&responseData) + if err != nil { + fmt.Println("Error decoding response:", err) + } + + if res.StatusCode == 200 { + return &responseData, nil + } + + fmt.Println("Error:", res.StatusCode) + fmt.Println("Error Description:", responseData.ErrorDescription) + + return nil, err +} diff --git a/api/apiuser.go b/api/apiuser.go new file mode 100644 index 0000000..738cfe4 --- /dev/null +++ b/api/apiuser.go @@ -0,0 +1,70 @@ +package api + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/doneill/er-cli-go/config" +) + +// ---------------------------------------------- +// stucts +// ---------------------------------------------- + +type UserResponse struct { + Data struct { + Username string `json:"username"` + Email string `json:"email"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + Role string `json:"role"` + IsStaff bool `json:"is_staff"` + IsSuperUser bool `json:"is_superuser"` + DateJoined string `json:"date_joined"` + ID string `json:"id"` + IsActive bool `json:"is_active"` + LastLogin string `json:"last_login"` + Pin string `json:"pin"` + Subject struct { + ID string `json:"id"` + } `json:"subject"` + Permissions struct { + Patrol []string `json:"patrol"` + MobileTests []string `json:"mobile_tests"` + } `json:"permissions"` + } `json:"data"` + ErrorDescription string `json:"error_description"` + Status struct { + Code int `json:"code"` + Message string `json:"message"` + } `json:"status"` +} + +// ---------------------------------------------- +// exported funtions +// ---------------------------------------------- + +func User() (*UserResponse, error) { + client := &http.Client{} + clientReq := getClientRequest(config.Sitename(), API_USER_ME, config.Token()) + + res, err := client.Do(&clientReq) + if err != nil { + fmt.Println("Error making request:", err) + } + var responseData UserResponse + err = json.NewDecoder(res.Body).Decode(&responseData) + if err != nil { + fmt.Println("Error decoding response:", err) + } + + if res.StatusCode == 200 { + return &responseData, nil + } + + fmt.Println("Error:", res.StatusCode) + fmt.Println("Error Description:", responseData.ErrorDescription) + + return nil, err +} diff --git a/api/earthranger_service.go b/api/earthranger_service.go deleted file mode 100644 index 2a41f44..0000000 --- a/api/earthranger_service.go +++ /dev/null @@ -1,74 +0,0 @@ -package api - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "strings" -) - -// ---------------------------------------------- -// const var -// ---------------------------------------------- - -const DOMAIN = ".pamdas.org" -const API_AUTH = "/oauth2/token" - -// ---------------------------------------------- -// stucts -// ---------------------------------------------- - -type Response struct { - AccessToken string `json:"access_token"` - ExpiresIn int `json:"expires_in"` - TokenType string `json:"token_type"` - Scope string `json:"scope"` - RefreshToken string `json:"refresh_token"` - ErrorDescription string `json:"error_description"` -} - -// ---------------------------------------------- -// exported funtions -// ---------------------------------------------- - -func Authenticate(sitename, username, password string) (*Response, error) { - // Create a new HTTP client and make a POST request to the authentication endpoint - client := &http.Client{} - req, err := http.NewRequest("POST", fmt.Sprintf("https://%s%s%s", sitename, DOMAIN, API_AUTH), nil) - if err != nil { - fmt.Println("Error creating request:", err) - } - - // Set the Content-Type and Accept headers on the request - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - req.Header.Set("Accept", "application/json") - - // Add the username, password, client_id, and grant_type to the request body - req.Body = io.NopCloser(strings.NewReader(fmt.Sprintf("username=%s&password=%s&client_id=er_mobile_tracker&grant_type=password", username, password))) - - // Make the POST request and get the response - res, err := client.Do(req) - if err != nil { - fmt.Println("Error making request:", err) - } - defer res.Body.Close() - - // Decode the JSON response from the authentication endpoint - var responseData Response - err = json.NewDecoder(res.Body).Decode(&responseData) - if err != nil { - fmt.Println("Error decoding response:", err) - } - - // If the request was successful, return the access token and expires in - if res.StatusCode == 200 { - return &responseData, nil - } - - // Print out the error and error description if the request was rejected - fmt.Println("Error:", res.StatusCode) - fmt.Println("Error Description:", responseData.ErrorDescription) - - return nil, err -} diff --git a/api/ersvc.go b/api/ersvc.go new file mode 100644 index 0000000..7c961ec --- /dev/null +++ b/api/ersvc.go @@ -0,0 +1,50 @@ +package api + +import ( + "fmt" + "net/http" +) + +// ---------------------------------------------- +// const endpoints +// ---------------------------------------------- + +const DOMAIN = ".pamdas.org" + +const API_V1 = "/api/v1.0" + +const API_AUTH = "/oauth2/token" + +const API_USER = API_V1 + "/user" + +const API_USER_ME = API_USER + "/me" + +// ---------------------------------------------- +// funtions +// ---------------------------------------------- + +func getApiUrl(sitename string, endpoint string) string { + return fmt.Sprintf("https://%s%s%s", sitename, DOMAIN, endpoint) +} + +func getAuthRequest(sitename string) http.Request { + req, err := http.NewRequest("POST", getApiUrl(sitename, API_AUTH), nil) + if err != nil { + fmt.Println("Error creating request:", err) + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set("Accept", "application/json") + + return *req +} + +func getClientRequest(sitename string, endpoint string, token string) http.Request { + req, err := http.NewRequest("GET", getApiUrl(sitename, endpoint), nil) + if err != nil { + fmt.Println("Error creating request:", err) + } + req.Header.Set("Authorization", "Bearer "+token) + req.Header.Set("Cache-control", "no-cache") + + return *req +} diff --git a/cmd/auth.go b/cmd/auth.go index b2504a2..22b1889 100644 --- a/cmd/auth.go +++ b/cmd/auth.go @@ -30,7 +30,7 @@ var authCmd = &cobra.Command{ } // ---------------------------------------------- -// funtions +// functions // ---------------------------------------------- func auth() { @@ -43,17 +43,18 @@ func auth() { } // Call the authenticate function to get the access token and expires in - response, err := api.Authenticate(SITENAME, USERNAME, password) + authResponse, err := api.Authenticate(SITENAME, USERNAME, password) if err != nil { fmt.Println("Error authenticating:", err) os.Exit(1) } // Print out the access token and expires in if the request was successful - if response != nil { + if authResponse != nil { viper.Set("user", USERNAME) - viper.Set("oauth_token", response.AccessToken) - viper.Set("expires", response.ExpiresIn) + viper.Set("sitename", SITENAME) + viper.Set("oauth_token", authResponse.AccessToken) + viper.Set("expires", authResponse.ExpiresIn) err := viper.WriteConfigAs(PROGRAM_NAME + CONFIG_TYPE) if err != nil { fmt.Println("Error writing configuration file:", err) diff --git a/cmd/token.go b/cmd/token.go index 3619950..49cd379 100644 --- a/cmd/token.go +++ b/cmd/token.go @@ -3,8 +3,8 @@ package cmd import ( "fmt" + "github.com/doneill/er-cli-go/config" "github.com/spf13/cobra" - "github.com/spf13/viper" ) // ---------------------------------------------- @@ -25,16 +25,8 @@ var tokenCmd = &cobra.Command{ // ---------------------------------------------- func token() { - if err := viper.ReadInConfig(); err != nil { - if _, ok := err.(viper.ConfigFileNotFoundError); ok { - fmt.Println("Error: er not configured properly, try reauthenticating") - } else { - fmt.Println("Error:", err) - } - } else { - var token = viper.Get("oauth_token") - fmt.Println(token) - } + var token = config.Token() + fmt.Println(token) } // ---------------------------------------------- diff --git a/cmd/user.go b/cmd/user.go new file mode 100644 index 0000000..0a8c94b --- /dev/null +++ b/cmd/user.go @@ -0,0 +1,62 @@ +package cmd + +import ( + "fmt" + "os" + + "github.com/doneill/er-cli-go/api" + "github.com/spf13/cobra" +) + +// ---------------------------------------------- +// user command +// ---------------------------------------------- + +var userCmd = &cobra.Command{ + Use: "user", + Short: "Current authenticated user data", + Long: `Return the currently authenticated er user data`, + Run: func(cmd *cobra.Command, args []string) { + user() + }, +} + +// ---------------------------------------------- +// functions +// ---------------------------------------------- + +func user() { + userResponse, err := api.User() + if err != nil { + fmt.Println("Error authenticating:", err) + os.Exit(1) + } + + if userResponse != nil { + formattedResponse := fmt.Sprintf("username: %s\nemail: %s\nfirst name: %s\nlast name: %s\nrole: %s\nis staff: %t\nis superuser: %t\ndate joined: %s\nid: %s\nisactive: %t\nlast login: %s\npin: %s\nsubject id: %s\npermissions:\n patrol: %v\nmobile tests: %v", + userResponse.Data.Username, + userResponse.Data.Email, + userResponse.Data.FirstName, + userResponse.Data.LastName, + userResponse.Data.Role, + userResponse.Data.IsStaff, + userResponse.Data.IsSuperUser, + userResponse.Data.DateJoined, + userResponse.Data.ID, + userResponse.Data.IsActive, + userResponse.Data.LastLogin, + userResponse.Data.Pin, + userResponse.Data.Subject.ID, + userResponse.Data.Permissions.Patrol, + userResponse.Data.Permissions.MobileTests) + fmt.Println(formattedResponse) + } +} + +// ---------------------------------------------- +// initialize +// ---------------------------------------------- + +func init() { + rootCmd.AddCommand(userCmd) +} diff --git a/config/util.go b/config/util.go new file mode 100644 index 0000000..fc2528d --- /dev/null +++ b/config/util.go @@ -0,0 +1,37 @@ +package config + +import ( + "fmt" + + "github.com/spf13/viper" +) + +// ---------------------------------------------- +// exported funtions +// ---------------------------------------------- + +func Sitename() string { + if err := viper.ReadInConfig(); err != nil { + if _, ok := err.(viper.ConfigFileNotFoundError); ok { + fmt.Println("Error: er not configured properly, try reauthenticating") + } else { + fmt.Println("Error:", err) + } + } else { + return viper.Get("sitename").(string) + } + return "" +} + +func Token() string { + if err := viper.ReadInConfig(); err != nil { + if _, ok := err.(viper.ConfigFileNotFoundError); ok { + fmt.Println("Error: er not configured properly, try reauthenticating") + } else { + fmt.Println("Error:", err) + } + } else { + return viper.Get("oauth_token").(string) + } + return "" +}