WIP: saves, finally
This commit is contained in:
parent
7db71b94b1
commit
b619b70d22
|
@ -1,4 +1,7 @@
|
|||
db.json
|
||||
*.bak
|
||||
*.tmp
|
||||
.*.sw*
|
||||
/cmd/again/again
|
||||
/again
|
||||
|
||||
|
|
|
@ -140,19 +140,36 @@ func (s *scheduler) Create(w http.ResponseWriter, r *http.Request) {
|
|||
// TODO validate user
|
||||
accessID := r.Context().Value("token").(string)
|
||||
|
||||
/*
|
||||
br, bw := io.Pipe()
|
||||
b := io.TeeReader(r.Body, bw)
|
||||
go func() {
|
||||
fmt.Println("reading from reader...")
|
||||
x, _ := ioutil.ReadAll(b)
|
||||
fmt.Println("cool beans and all")
|
||||
fmt.Println(string(x))
|
||||
bw.Close()
|
||||
}()
|
||||
decoder := json.NewDecoder(br)
|
||||
*/
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
sched := &again.Schedule{}
|
||||
err := decoder.Decode(s)
|
||||
err := decoder.Decode(sched)
|
||||
if nil != err {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
fmt.Printf("New Schedule:\n%#v\n", sched)
|
||||
|
||||
// TODO validate and modify
|
||||
sched.AccessID = accessID
|
||||
sched2, err := s.DB.Set(*sched)
|
||||
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)
|
||||
buf, err := json.Marshal(sched2)
|
||||
if nil != err {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package jsondb
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/subtle"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
@ -89,11 +92,15 @@ type Schedule struct {
|
|||
Webhooks []again.Webhook `json:"webhooks" db"webhooks"`
|
||||
}
|
||||
|
||||
func ctcmp(x string, y string) bool {
|
||||
return 1 == subtle.ConstantTimeCompare([]byte(x), []byte(y))
|
||||
}
|
||||
|
||||
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 {
|
||||
if !s.Disabled && ctcmp(accessID, s.AccessID) {
|
||||
schedules = append(schedules, &again.Schedule{
|
||||
ID: s.ID,
|
||||
AccessID: s.AccessID,
|
||||
|
@ -108,25 +115,41 @@ func (db *JSONDB) List(accessID string) ([]*again.Schedule, error) {
|
|||
return schedules, nil
|
||||
}
|
||||
|
||||
func (db *JSONDB) get(id string) *Schedule {
|
||||
func (db *JSONDB) get(id string) (int, *Schedule) {
|
||||
for i := range db.json.Schedules {
|
||||
schedule := db.json.Schedules[i]
|
||||
if id == schedule.AccessID {
|
||||
return &schedule
|
||||
if ctcmp(id, schedule.ID) {
|
||||
return i, &schedule
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func genID() (string, error) {
|
||||
b := make([]byte, 16)
|
||||
_, err := rand.Read(b)
|
||||
if nil != err {
|
||||
return "", err
|
||||
}
|
||||
return hex.EncodeToString(b), 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
|
||||
exists := false
|
||||
index := -1
|
||||
if "" == s.ID {
|
||||
id, err := genID()
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
s.ID = id
|
||||
} else {
|
||||
i, old := db.get(s.ID)
|
||||
index = i
|
||||
exists = nil != old
|
||||
if !exists || !ctcmp(old.AccessID, s.AccessID) {
|
||||
return nil, fmt.Errorf("invalid id")
|
||||
}
|
||||
newSchedules = append(newSchedules, old)
|
||||
}
|
||||
|
||||
schedule := Schedule{
|
||||
|
@ -138,7 +161,12 @@ func (db *JSONDB) Set(s again.Schedule) (*again.Schedule, error) {
|
|||
NextRunAt: s.NextRunAt,
|
||||
Webhooks: s.Webhooks,
|
||||
}
|
||||
newSchedules = append(newSchedules, schedule)
|
||||
|
||||
if exists {
|
||||
db.json.Schedules[index] = schedule
|
||||
} else {
|
||||
db.json.Schedules = append(db.json.Schedules, schedule)
|
||||
}
|
||||
|
||||
err := db.save(s.AccessID)
|
||||
if nil != err {
|
||||
|
@ -150,17 +178,32 @@ func (db *JSONDB) Set(s again.Schedule) (*again.Schedule, error) {
|
|||
|
||||
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)
|
||||
tmppath := db.path + ".tmp"
|
||||
bakpath := db.path + ".bak"
|
||||
|
||||
os.Remove(tmppath) // ignore error
|
||||
f, err := os.OpenFile(tmppath, os.O_RDWR|os.O_CREATE, 0700)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
encoder := json.NewEncoder(f)
|
||||
err = encoder.Encode(db.json.Schedules)
|
||||
err = encoder.Encode(db.json)
|
||||
f.Close()
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
os.Remove(bakpath) // ignore error
|
||||
err = os.Rename(db.path, bakpath)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.Rename(tmppath, db.path)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
d = new Date(d.valueOf() + minutes * 60 * 1000);
|
||||
$('.js-date').value = d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate());
|
||||
$('.js-time').value = pad(d.getHours()) + ':' + pad(d.getMinutes());
|
||||
$('.js-url').value = 'https://enfqtbjh5ghw.x.pipedream.net';
|
||||
|
||||
console.log('hello');
|
||||
|
||||
|
@ -88,11 +89,9 @@
|
|||
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
|
||||
},
|
||||
tz: $('.js-tz', $hook).value,
|
||||
webhooks: []
|
||||
};
|
||||
var hook = {
|
||||
|
@ -139,11 +138,12 @@
|
|||
return resp
|
||||
.json()
|
||||
.then(function(data) {
|
||||
if (!data.schedule) {
|
||||
if (!data.date || !data.webhooks) {
|
||||
console.error(data);
|
||||
throw new Error('something bad happened');
|
||||
}
|
||||
|
||||
state.account.schedules.webhooks.push(resp.data.schedule);
|
||||
state.account.schedules.push(resp.data);
|
||||
|
||||
displayAccount(state.account);
|
||||
})
|
||||
|
@ -318,17 +318,35 @@
|
|||
})
|
||||
);
|
||||
$('.js-schedules-list').hidden = true;
|
||||
$('.js-schedules').hidden = false;
|
||||
return window
|
||||
.fetch('/api/v0/schedules', {
|
||||
headers: { Authorization: getToken() }
|
||||
})
|
||||
.then(function(resp) {
|
||||
return resp.json().then(function(schedules) {
|
||||
return resp
|
||||
.clone()
|
||||
.json()
|
||||
.then(function(schedules) {
|
||||
allSchedules = schedules;
|
||||
renderSchedules(schedules);
|
||||
$('.js-schedules').hidden = false;
|
||||
})
|
||||
.catch(function(e) {
|
||||
console.error("Didn't parse JSON:");
|
||||
console.error(e);
|
||||
console.log(resp);
|
||||
$('.js-schedules-list').hidden = false;
|
||||
window.alert(resp.status + ': ' + resp.statusText);
|
||||
return resp.text().then(function(text) {
|
||||
window.alert(text);
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(function(e) {
|
||||
console.error('Request Error');
|
||||
console.error(e);
|
||||
window.alert('Network error. Are you online?');
|
||||
});
|
||||
}
|
||||
|
||||
function renderSchedules(schedules) {
|
||||
|
|
|
@ -22,9 +22,7 @@
|
|||
<div class="js-schedule">
|
||||
<form class="js-new-schedule">
|
||||
<label>Date: <input type="date" class="js-date" required/></label>
|
||||
<label
|
||||
>Time: <input type="time" class="js-time" step="60" required
|
||||
/></label>
|
||||
<label>Time: <input type="time" class="js-time" step="300" required/></label>
|
||||
<!-- TODO combo box -->
|
||||
<label
|
||||
>Location:
|
||||
|
@ -39,10 +37,7 @@
|
|||
<h3>Webhook</h3>
|
||||
<div class="js-webhooks">
|
||||
<div class="js-webhook">
|
||||
<h4>
|
||||
<span class="js-comment"></span
|
||||
><button class="js-delete" type="button">Delete</button>
|
||||
</h4>
|
||||
<h4><span class="js-comment"></span><button class="js-delete" type="button">Delete</button></h4>
|
||||
<span class="js-id" hidden></span>
|
||||
<span class="js-method"></span>
|
||||
<span class="js-url"></span>
|
||||
|
@ -67,23 +62,13 @@
|
|||
</select>
|
||||
<br />
|
||||
-->
|
||||
<input
|
||||
class="js-comment"
|
||||
type="text"
|
||||
placeholder="Webhook Name"
|
||||
required
|
||||
/>
|
||||
<input class="js-comment" type="text" placeholder="Webhook Name" required />
|
||||
<br />
|
||||
<select class="js-method">
|
||||
<option value="POST" selected>POST</option>
|
||||
<option value="PUT">PUT</option>
|
||||
</select>
|
||||
<input
|
||||
placeholder="https://example.com/api/v1/updates"
|
||||
class="js-url"
|
||||
type="url"
|
||||
required
|
||||
/>
|
||||
<input placeholder="https://example.com/api/v1/updates" class="js-url" type="url" required />
|
||||
<div class="js-headers">
|
||||
<div class="js-header">
|
||||
<input placeholder="Header" class="js-key" type="text" />
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package webooks
|
||||
|
||||
type Webhook struct {
|
||||
Name string `json:"name"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Comment string `json:"comment"`
|
||||
Method string `json:"method"`
|
||||
URL string `json:"url"`
|
||||
Auth map[string]string `json:"auth"`
|
||||
Headers map[string]string `json:"headers"`
|
||||
Form map[string]string `json:"form"`
|
||||
JSON map[string]string `json:"json"`
|
||||
Config map[string]string `json:"config"`
|
||||
Auth map[string]string `json:"auth,omitempty"`
|
||||
Headers map[string]string `json:"headers,omitempty"`
|
||||
Form map[string]string `json:"form,omitempty"`
|
||||
JSON map[string]string `json:"json,omitempty"`
|
||||
Config map[string]string `json:"config,omitempty"`
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue