예제 #1
0
파일: accept.go 프로젝트: fedgrant/tonika
func (fe *FrontEnd) replyAdminAccept(req *http.Request) *http.Response {
	args, err := http.ParseQuery(req.URL.RawQuery)
	if err != nil {
		return buildResp("Invalid accept link")
	}
	// Read SignatureKey
	s, ok := args["sk"]
	if !ok || s == nil || len(s) != 1 {
		return buildResp("Invalid accept link")
	}
	sigkeyText := s[0]
	_, err = sys.ParseSigPubKey(sigkeyText)
	if err != nil {
		return buildResp("Invalid accept link")
	}
	// Read DialKey
	d, ok := args["dk"]
	if !ok || d == nil || len(d) != 1 {
		return buildResp("Invalid accept link")
	}
	dialkeyText := d[0]
	dialkey, err := sys.ParseDialKey(dialkeyText)
	if err != nil {
		return buildResp("Invalid accept link")
	}
	// Read AcceptKey (optional)
	a, ok := args["ak"]
	var acceptkey *sys.DialKey
	if ok && a != nil && len(a) == 1 {
		acceptkey, err = sys.ParseDialKey(a[0])
		if err != nil {
			return buildResp("Invalid accept link")
		}
	}
	// Read Name
	var name string
	n, ok := args["na"]
	if ok && n != nil && len(n) == 1 {
		name = n[0]
	}
	// Read Email
	var email string
	e, ok := args["em"]
	if ok && e != nil && len(e) == 1 {
		email = e[0]
	}
	// Read Addr
	var addr string
	ad, ok := args["ad"]
	if ok && ad != nil && len(ad) == 1 {
		addr = ad[0]
	}

	// Reconcile with local database
	var v sys.View
	if acceptkey != nil {
		v, err = fe.bank.GetByAcceptKey(acceptkey)
		if err != nil {
			v = nil
		}
	}
	if v == nil {
		v, err = fe.bank.GetByDialKey(dialkey)
		if err != nil {
			v = nil
		}
	}
	if v != nil {
		if v.GetName() != "" {
			name = v.GetName()
		}
		if v.GetEmail() != "" {
			email = v.GetEmail()
		}
		if v.GetAddr() != "" {
			addr = v.GetAddr()
		}
	}
	var slotText string
	if v != nil {
		slotText = strconv.Itoa(v.GetSlot())
	}

	// prepare content
	data := acceptData{
		Name:     name,
		Email:    email,
		Addr:     addr,
		Slot:     slotText,
		DialKey:  dialkeyText,
		SigKey:   sigkeyText,
		AdminURL: fe.adminURL,
	}
	var w bytes.Buffer
	err = fe.tmplAccept.Execute(&data, &w)
	if err != nil {
		return newRespServiceUnavailable()
	}

	// prepare page
	pdata := pageData{
		Title:      sys.Name + " — Accept invitation?",
		CSSLinks:   []string{"accept.css"},
		JSLinks:    []string{"accept.js"},
		GridLayout: "",
		Content:    w.String(),
	}
	var w2 bytes.Buffer
	err = fe.tmplPage.Execute(&pdata, &w2)
	if err != nil {
		return newRespServiceUnavailable()
	}
	return buildResp(w2.String())
}
예제 #2
0
func (fe *FrontEnd) replyAPIAccept(args map[string][]string) *http.Response {
	// name and email args
	na, ok := args["na"]
	if !ok || na == nil || len(na) != 1 {
		return newRespBadRequest()
	}

	em, ok := args["em"]
	if !ok || em == nil || len(em) != 1 {
		return newRespBadRequest()
	}

	ad, ok := args["ad"]
	if !ok || ad == nil || len(ad) != 1 {
		return newRespBadRequest()
	}

	sl, ok := args["sl"]
	if !ok || sl == nil || len(sl) != 1 {
		return newRespBadRequest()
	}

	dk, ok := args["dk"]
	if !ok || dk == nil || len(dk) != 1 {
		return newRespBadRequest()
	}
	dialkey, err := sys.ParseDialKey(dk[0])
	if err != nil {
		return newRespBadRequest()
	}

	sk, ok := args["sk"]
	if !ok || sk == nil || len(sk) != 1 {
		return newRespBadRequest()
	}
	sigkey, err := sys.ParseSigPubKey(sk[0])
	if err != nil {
		return newRespBadRequest()
	}

	// Logic
	result := &apiAcceptResult{}
	s, err := strconv.Atoi(sl[0])
	var v sys.View
	adding := false
	if err == nil {
		v, err = fe.bank.GetBySlot(s)
		if err != nil {
			v = nil
		}
	}
	if v == nil {
		v, err = fe.bank.GetByDialKey(dialkey)
		if err != nil {
			v = nil
		}
	}
	if v == nil {
		v = fe.bank.Reserve()
		s = v.GetSlot()
		adding = true
	}

	if na[0] != "" {
		fe.bank.Write(s, "Name", na[0])
	}
	if em[0] != "" {
		fe.bank.Write(s, "Email", em[0])
	}
	if ad[0] != "" {
		fe.bank.Write(s, "Addr", ad[0])
	}
	_, err = fe.bank.Write(s, "SignatureKey", sigkey)
	if err != nil {
		result.ErrMsg = "This friend's invite has already been accepted."
	}
	_, err = fe.bank.Write(s, "DialKey", dialkey)
	if err != nil {
		result.ErrMsg = "This friend's invite has already been accepted."
	}
	if adding {
		result.InviteMsg = fe.makeInvite(v)
	}

	fe.bank.Sync(s)
	fe.bank.Save()

	jb, err := json.Marshal(&result)
	if err != nil {
		return newRespServiceUnavailable()
	}
	return buildResp(string(jb))
}
예제 #3
0
파일: db.go 프로젝트: fedgrant/tonika
func ReadFriendDb(path string) (*buttress, os.Error) {
	// Read contents
	bytes, err := ioutil.ReadFile(path)
	if err != nil {
		log.Stderrf("Cannot read from friends file \"%s\"\n", path)
		return nil, &Error{ErrLoad, err}
	}
	// Unmarshal json
	book := jsonDb{}
	if err := json.Unmarshal(bytes, &book); err != nil {
		log.Stderrf("Error decoding friends file [%s] json. "+
			"Offending token [%s].\n",
			path, err)
		return nil, &Error{ErrDecode, err}
	}
	db := &buttress{me: &sys.Me{}, recs: make(map[int]*friend), path: path}

	// Deep parse me-data
	db.me = &sys.Me{
		Name:    book.Me.Name,
		Addr:    book.Me.Addr,
		ExtAddr: book.Me.ExtAddr,
		Email:   book.Me.Email,
	}
	id, err := sys.ParseId(book.Me.Id)
	if err != nil {
		log.Stderrf("Error [%v] decoding my ID [%s]\n", err, book.Me.Id)
		return nil, &Error{ErrDecode, book.Me.Id}
	}
	db.me.Id = id
	pk, err := sys.ParseSigKey(book.Me.SigKey)
	if err != nil {
		log.Stderrf("Error [%v] decoding my signature key [%s]\n",
			err, book.Me.SigKey)
		return nil, &Error{ErrDecode, book.Me.SigKey}
	}
	db.me.SignatureKey = pk

	// Deep parse friends
	if book.Friends != nil {
		for i := 0; i < len(book.Friends); i++ {
			// slot
			slot, err := strconv.Atoi(book.Friends[i].Slot)
			if err != nil || slot < 0 {
				log.Stderrf("db, invalid slot number, skipping friends")
				continue
			}
			// id
			id1, err := sys.ParseId(book.Friends[i].Id)
			var id *sys.Id
			if err == nil {
				id = &id1
			}

			// dial key
			dkey, _ := sys.ParseDialKey(book.Friends[i].DialKey)

			// accept key
			akey, _ := sys.ParseDialKey(book.Friends[i].AcceptKey)

			// sig key
			sigk, err := sys.ParseSigPubKey(book.Friends[i].SigKey)

			// hello key
			hellok, err := sys.ParseHelloKey(book.Friends[i].HelloKey)

			// make
			fr := &friend{
				Friend: sys.Friend{
					Slot:         slot,
					Id:           id,
					SignatureKey: sigk,
					HelloKey:     hellok,
					DialKey:      dkey,
					AcceptKey:    akey,
					Name:         book.Friends[i].Name,
					Email:        book.Friends[i].Email,
					Addr:         book.Friends[i].Addr,
					Rest:         book.Friends[i].Rest,
				},
				online: false,
			}
			_, present := db.recs[fr.Slot]
			if present {
				log.Stderrf("Duplicate friend, using latest\n")
			}
			db.recs[fr.Slot] = fr
		} // for
	}
	return db, nil
}