Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

devices handler #23

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added cmd/devices/main
Binary file not shown.
126 changes: 126 additions & 0 deletions cmd/devices/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package main

import (
"database/sql"
"encoding/json"
"flag"
"fmt"
"log"
"net/http"
"time"

_ "github.com/go-sql-driver/mysql"
)

type rawTime []byte

func (t rawTime) Time() (time.Time, error) {
if string(t) == "0000-00-00 00:00:00" {
return time.Time{}, nil
}
return time.Parse("2006-01-02 15:04:05", string(t))
}

func (t rawTime) Format(layout string) (string, error) {
gt, err := t.Time()
if err != nil {
return "", err
}
return gt.Format(layout), nil
}

type Enrollment struct {
Id string `json:"id"`
DeviceID string `json:"device_id"`
UserId sql.NullString `json:"user_id"`
Type string `json:"type"`
Topic string `json:"topic"`
Enabled string `json:"enabled"`
PushMagic string `json:"push_magic"`
TokenHex string `json:"token_hex"`
LastSeenAt rawTime `json:"last_seen_at"`
TokenUpdateTally string `json:"token_update_tally"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}

type DEPProfileStatus string

type DeviceDTO struct {
SerialNumber string `json:"serial_number"`
UDID string `json:"udid"`
EnrollmentStatus bool `json:"enrollment_status"`
LastSeen string `json:"last_seen"`
DEPProfileStatus DEPProfileStatus `json:"dep_profile_status"`
}

var (
dsn string
)

func main() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This main() should remain here in main.go under devices

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is under /devices? I'm not sure what you mean.

flag.StringVar(&dsn, "dsn", "", "data source name (e.g. connection string or path)")
flag.Parse()
db, err := sql.Open("mysql", dsn)
if err != nil {
log.Fatal(err)
}
rows, err := db.Query(`select * from enrollments;`)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be migrated to the internal folder if this logic is to only remain here....keeps the main function clean as it just calls the executing functions that are required. --> internal/devices module

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point. will work on this.

if err != nil {
log.Fatal(err)
}
defer rows.Close()
var devices []DeviceDTO
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would also create a types for all these under that new internal/devices module to keep this cleaner

for rows.Next() {
var e Enrollment
if err := rows.Scan(&e.Id, &e.DeviceID, &e.UserId, &e.Type, &e.Topic, &e.PushMagic, &e.TokenHex, &e.Enabled, &e.TokenUpdateTally, &e.LastSeenAt, &e.CreatedAt, &e.UpdatedAt); err != nil {
fmt.Println("failed parsing enrollment")
log.Fatal(err)
}
lsa, err := e.LastSeenAt.Format(time.RFC3339Nano)
if err != nil {
fmt.Println("failed parsing time")
log.Fatal(err)
}
ddto := DeviceDTO{
UDID: e.Id,
EnrollmentStatus: func(enabled string) bool {
return enabled == "1"
}(e.Enabled),
LastSeen: lsa,
DEPProfileStatus: "unknown",
}
type Serial struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same with the types suggestion, migrate all of these to a types folder or try to consolidate types if possible for readability.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kind of disagree that Serial is worthy of being stuffed in another package somewhere. It's such a small struct that is only used here, in-line. I also don't really like the types pattern as I'd prefer to organize by business logic instead of go type.

Serial string `json:"serial_number"`
}
rows, err = db.Query(`select serial_number from devices where id = ?`, e.Id)
if err != nil {
fmt.Println("failed querying serial")
log.Fatal(err)
}
defer rows.Close()
var s Serial
for rows.Next() {
if err := rows.Scan(
&s.Serial,
); err != nil {
fmt.Println("failed querying serial")
log.Fatal(err)
}
}
ddto.SerialNumber = s.Serial
devices = append(devices, ddto)
}

devicesHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would create a separate handlers for this. Honestly, the handler that I refactored in enroll_endpoint is very simple and allows us to add a quick logger and is pretty easy to understand the routing. Since the main purpose of this is to serve as a HTTP server, it is very clear then it should operate like that vs a CLI tool that offers up an HTTP server interface

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clarify your comment "would create a separate handlers" for this. I'm not sure what you mean.

w.WriteHeader(http.StatusCreated)
w.Header().Set("Content-Type", "application/json")
jsonResp, err := json.Marshal(devices)
if err != nil {
log.Fatalf("Error happened in JSON marshal. Err: %s", err)
}
w.Write(jsonResp)
})
http.Handle("/devices", devicesHandler)
http.ListenAndServe(":8080", nil)
}