WIP: stuff for saving
This commit is contained in:
		
							parent
							
								
									f135020914
								
							
						
					
					
						commit
						7db71b94b1
					
				
							
								
								
									
										11
									
								
								again.go
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								again.go
									
									
									
									
									
								
							| @ -7,9 +7,16 @@ import ( | ||||
| 	webhooks "git.rootprojects.org/root/go-again/webhooks" | ||||
| ) | ||||
| 
 | ||||
| type Webhook webhooks.Webhook | ||||
| 
 | ||||
| type Schedule struct { | ||||
| 	NextRunAt time.Time | ||||
| 	Webhooks  []webhooks.Webhook | ||||
| 	ID        string    `json:"id" db:"id"` | ||||
| 	AccessID  string    `json:"-" db:"access_id"` | ||||
| 	Date      string    `json:"date" db:"date"` | ||||
| 	Time      string    `json:"time" db:"time"` | ||||
| 	TZ        string    `json:"tz" db:"tz"` | ||||
| 	NextRunAt time.Time `json:"next_run_at" db:"next_run_at"` | ||||
| 	Webhooks  []Webhook `json:"webhooks" db"webhooks"` | ||||
| } | ||||
| 
 | ||||
| // https://yourbasic.org/golang/time-change-convert-location-timezone/ | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| @ -85,7 +86,8 @@ func main() { | ||||
| } | ||||
| 
 | ||||
| type ScheduleDB interface { | ||||
| 	List() ([]again.Schedule, error) | ||||
| 	List(string) ([]*again.Schedule, error) | ||||
| 	Set(again.Schedule) (*again.Schedule, error) | ||||
| } | ||||
| 
 | ||||
| type scheduler struct { | ||||
| @ -93,12 +95,17 @@ type scheduler struct { | ||||
| } | ||||
| 
 | ||||
| func (s *scheduler) Handle(w http.ResponseWriter, r *http.Request) { | ||||
| 	// note: no go-routines reading body in handlers to follow | ||||
| 	defer r.Body.Close() | ||||
| 
 | ||||
| 	token := strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ") | ||||
| 	if "" == token { | ||||
| 	if 32 != len(token) { | ||||
| 		http.Error(w, "Authorization Header did not contain a valid token", http.StatusForbidden) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx := r.Context() | ||||
| 	ctx = context.WithValue(ctx, "token", token) | ||||
| 	r = r.WithContext(ctx) | ||||
| 
 | ||||
| 	fmt.Println("whatever", r.Method, r.URL) | ||||
| 	switch r.Method { | ||||
| @ -106,7 +113,7 @@ func (s *scheduler) Handle(w http.ResponseWriter, r *http.Request) { | ||||
| 		s.List(w, r) | ||||
| 		return | ||||
| 	case http.MethodPost: | ||||
| 		http.Error(w, "Not Implemented", http.StatusNotImplemented) | ||||
| 		s.Create(w, r) | ||||
| 		return | ||||
| 	default: | ||||
| 		http.Error(w, "Not Implemented", http.StatusNotImplemented) | ||||
| @ -115,7 +122,8 @@ func (s *scheduler) Handle(w http.ResponseWriter, r *http.Request) { | ||||
| } | ||||
| 
 | ||||
| func (s *scheduler) List(w http.ResponseWriter, r *http.Request) { | ||||
| 	schedules, err := s.DB.List() | ||||
| 	accessID := r.Context().Value("token").(string) | ||||
| 	schedules, err := s.DB.List(accessID) | ||||
| 	if nil != err { | ||||
| 		http.Error(w, err.Error(), http.StatusInternalServerError) | ||||
| 		return | ||||
| @ -127,3 +135,27 @@ func (s *scheduler) List(w http.ResponseWriter, r *http.Request) { | ||||
| 	} | ||||
| 	w.Write(buf) | ||||
| } | ||||
| 
 | ||||
| func (s *scheduler) Create(w http.ResponseWriter, r *http.Request) { | ||||
| 	// TODO validate user | ||||
| 	accessID := r.Context().Value("token").(string) | ||||
| 
 | ||||
| 	decoder := json.NewDecoder(r.Body) | ||||
| 	sched := &again.Schedule{} | ||||
| 	err := decoder.Decode(s) | ||||
| 	if nil != err { | ||||
| 		http.Error(w, err.Error(), http.StatusInternalServerError) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// TODO validate and modify | ||||
| 	sched.AccessID = accessID | ||||
| 	s.DB.Set(*sched) | ||||
| 
 | ||||
| 	buf, err := json.Marshal(sched) | ||||
| 	if nil != err { | ||||
| 		http.Error(w, err.Error(), http.StatusInternalServerError) | ||||
| 		return | ||||
| 	} | ||||
| 	w.Write(buf) | ||||
| } | ||||
|  | ||||
| @ -6,18 +6,19 @@ import ( | ||||
| 	"net/url" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	again "git.rootprojects.org/root/go-again" | ||||
| ) | ||||
| 
 | ||||
| type JSONDB struct { | ||||
| 	dburl string | ||||
| 	file  *os.File | ||||
| 	path  string | ||||
| 	json  *dbjson | ||||
| } | ||||
| 
 | ||||
| type dbjson struct { | ||||
| 	Schedules []again.Schedule `json:"schedules"` | ||||
| 	Schedules []Schedule `json:"schedules"` | ||||
| } | ||||
| 
 | ||||
| func Connect(dburl string) (*JSONDB, error) { | ||||
| @ -50,9 +51,11 @@ func Connect(dburl string) (*JSONDB, error) { | ||||
| 	stat, err := f.Stat() | ||||
| 	if 0 == stat.Size() { | ||||
| 		_, err := f.Write([]byte(`{"schedules":[]}`)) | ||||
| 		f.Close() | ||||
| 		if nil != err { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 
 | ||||
| 		f, err = os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0700) | ||||
| 		if nil != err { | ||||
| 			return nil, err | ||||
| @ -62,17 +65,102 @@ func Connect(dburl string) (*JSONDB, error) { | ||||
| 	decoder := json.NewDecoder(f) | ||||
| 	db := &dbjson{} | ||||
| 	err = decoder.Decode(db) | ||||
| 	f.Close() | ||||
| 	if nil != err { | ||||
| 		return nil, fmt.Errorf("Couldn't parse %q as JSON: %s", path, err) | ||||
| 	} | ||||
| 
 | ||||
| 	return &JSONDB{ | ||||
| 		dburl: dburl, | ||||
| 		file:  f, | ||||
| 		path:  path, | ||||
| 		json:  db, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func (db *JSONDB) List() ([]again.Schedule, error) { | ||||
| 	return db.json.Schedules, nil | ||||
| // A copy of again.Schedule, but with access_id json-able | ||||
| type Schedule struct { | ||||
| 	ID        string          `json:"id" db:"id"` | ||||
| 	AccessID  string          `json:"access_id" db:"access_id"` | ||||
| 	Date      string          `json:"date" db:"date"` | ||||
| 	Time      string          `json:"time" db:"time"` | ||||
| 	TZ        string          `json:"tz" db:"tz"` | ||||
| 	NextRunAt time.Time       `json:"next_run_at" db:"next_run_at"` | ||||
| 	Disabled  bool            `json:"disabled" db:"disabled"` | ||||
| 	Webhooks  []again.Webhook `json:"webhooks" db"webhooks"` | ||||
| } | ||||
| 
 | ||||
| func (db *JSONDB) List(accessID string) ([]*again.Schedule, error) { | ||||
| 	schedules := []*again.Schedule{} | ||||
| 	for i := range db.json.Schedules { | ||||
| 		s := db.json.Schedules[i] | ||||
| 		if !s.Disabled && accessID == s.AccessID { | ||||
| 			schedules = append(schedules, &again.Schedule{ | ||||
| 				ID:        s.ID, | ||||
| 				AccessID:  s.AccessID, | ||||
| 				Date:      s.Date, | ||||
| 				Time:      s.Time, | ||||
| 				TZ:        s.TZ, | ||||
| 				NextRunAt: s.NextRunAt, | ||||
| 				Webhooks:  s.Webhooks, | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
| 	return schedules, nil | ||||
| } | ||||
| 
 | ||||
| func (db *JSONDB) get(id string) *Schedule { | ||||
| 	for i := range db.json.Schedules { | ||||
| 		schedule := db.json.Schedules[i] | ||||
| 		if id == schedule.AccessID { | ||||
| 			return &schedule | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (db *JSONDB) Set(s again.Schedule) (*again.Schedule, error) { | ||||
| 	newSchedules := []Schedule{} | ||||
| 
 | ||||
| 	for i := range db.json.Schedules { | ||||
| 		old := db.json.Schedules[i] | ||||
| 		if s.ID == old.AccessID { | ||||
| 			continue | ||||
| 		} | ||||
| 		newSchedules = append(newSchedules, old) | ||||
| 	} | ||||
| 
 | ||||
| 	schedule := Schedule{ | ||||
| 		ID:        s.ID, | ||||
| 		AccessID:  s.AccessID, | ||||
| 		Date:      s.Date, | ||||
| 		Time:      s.Time, | ||||
| 		TZ:        s.TZ, | ||||
| 		NextRunAt: s.NextRunAt, | ||||
| 		Webhooks:  s.Webhooks, | ||||
| 	} | ||||
| 	newSchedules = append(newSchedules, schedule) | ||||
| 
 | ||||
| 	err := db.save(s.AccessID) | ||||
| 	if nil != err { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return &s, nil | ||||
| } | ||||
| 
 | ||||
| func (db *JSONDB) save(accessID string) error { | ||||
| 	// TODO per-user files (w/ mutex lock or channel on open and write) | ||||
| 	f, err := os.OpenFile(db.path, os.O_RDWR|os.O_CREATE, 0700) | ||||
| 	if nil != err { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	encoder := json.NewEncoder(f) | ||||
| 	err = encoder.Encode(db.json.Schedules) | ||||
| 	f.Close() | ||||
| 	if nil != err { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @ -87,16 +87,22 @@ | ||||
| 	function newSchedule() { | ||||
| 		var $hook = $('.js-schedule'); | ||||
| 		//var deviceId = $hook.closest('.js-schedule').querySelector('.js-id').value;
 | ||||
| 		var schedule = { | ||||
| 			schedule: { | ||||
| 				date: $('.js-date', $hook).value, | ||||
| 				time: $('.js-time', $hook).value, | ||||
| 				tz: $('.js-tz', $hook).value | ||||
| 			}, | ||||
| 			webhooks: [] | ||||
| 		}; | ||||
| 		var hook = { | ||||
| 			date: $('.js-date', $hook).value, | ||||
| 			time: $('.js-time', $hook).value, | ||||
| 			tz: $('.js-tz', $hook).value, | ||||
| 			comment: $('.js-comment', $hook).value, | ||||
| 			method: $('.js-method', $hook).value, | ||||
| 			url: $('.js-url', $hook).value, | ||||
| 			headers: {} | ||||
| 		}; | ||||
| 		console.log('schedule:', hook); | ||||
| 		schedule.webhooks.push(hook); | ||||
| 		console.log('schedule:', schedule); | ||||
| 		$$('.js-header', $hook).forEach(function($head) { | ||||
| 			var key = $('.js-key', $head).value; | ||||
| 			var val = $('.js-value', $head).value; | ||||
| @ -114,7 +120,7 @@ | ||||
| 				Authorization: getToken(), | ||||
| 				'Content-Type': 'application/json' | ||||
| 			}, | ||||
| 			body: JSON.stringify(hook), | ||||
| 			body: JSON.stringify(schedule), | ||||
| 			cors: true | ||||
| 		}; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user