func (self *channelAPI) Blob_Permission(perma grapher.PermaNode, permission grapher.PermissionNode) { mutJson := map[string]interface{}{"perma": perma.BlobRef(), "seq": permission.SequenceNumber(), "type": "permission", "user": permission.UserName(), "allow": permission.AllowBits(), "deny": permission.DenyBits(), "blobref": permission.BlobRef()} switch permission.Action() { case grapher.PermAction_Invite: mutJson["action"] = "invite" case grapher.PermAction_Expel: mutJson["action"] = "expel" case grapher.PermAction_Change: mutJson["action"] = "change" default: panic("Unknown action") } schema, err := json.Marshal(mutJson) if err != nil { panic(err.String()) } if self.bufferOnly { self.messageBuffer = append(self.messageBuffer, string(schema)) } else { err = self.forwardToFollowers(perma.BlobRef(), string(schema)) } if err != nil { log.Printf("Err Forward: %v", err) } }
func (self *channelAPI) Blob_Mutation(perma grapher.PermaNode, mutation grapher.MutationNode) { mutJson := map[string]interface{}{"perma": perma.BlobRef(), "seq": mutation.SequenceNumber(), "type": "mutation", "signer": mutation.Signer(), "entity": mutation.EntityBlobRef(), "field": mutation.Field(), "time": mutation.Time()} switch mutation.Operation().(type) { case []ot.StringOperation: op := mutation.Operation().([]ot.StringOperation) // The following two lines work around a problem in GO/JSON mutJson["op"] = &op case []byte: msg := json.RawMessage(mutation.Operation().([]byte)) mutJson["op"] = &msg default: panic("Unsupported operation kind") } schema, err := json.Marshal(mutJson) if err != nil { panic(err.String()) } if self.bufferOnly { self.messageBuffer = append(self.messageBuffer, string(schema)) } else { err = self.forwardToFollowers(perma.BlobRef(), string(schema)) } if err != nil { log.Printf("Err Forward: %v", err) } }
func (self *dummyAPI) Signal_ReceivedInvitation(perma grapher.PermaNode, permission grapher.PermissionNode) { log.Printf("APP %v: Received Invitation", self.userID) // Automatically accept the invitation _, err := self.grapher.CreateKeepBlob(perma.BlobRef(), permission.BlobRef()) if err != nil { self.t.Fatal(err.String()) } }
func (self *channelAPI) Signal_AcceptedInvitation(perma grapher.PermaNode, permission grapher.PermissionNode, keep grapher.KeepNode) { msgJson := map[string]interface{}{"perma": perma.BlobRef(), "type": "accept", "signer": permission.Signer(), "permission": permission.BlobRef()} schema, err := json.Marshal(msgJson) if err != nil { panic(err.String()) } if self.bufferOnly { self.messageBuffer = append(self.messageBuffer, string(schema)) } else { err = self.forwardToUser(keep.Signer(), string(schema)) } if err != nil { log.Printf("Err Forward: %v", err) } }
func (self *channelAPI) Blob_DeleteEntity(perma grapher.PermaNode, entity grapher.DelEntityNode) { entityJson := map[string]interface{}{"perma": perma.BlobRef(), "seq": entity.SequenceNumber(), "type": "delentity", "signer": entity.Signer(), "blobref": entity.BlobRef(), "entity": entity.EntityBlobRef()} schema, err := json.Marshal(entityJson) if err != nil { panic(err.String()) } if self.bufferOnly { self.messageBuffer = append(self.messageBuffer, string(schema)) } else { err = self.forwardToFollowers(perma.BlobRef(), string(schema)) } if err != nil { log.Printf("Err Forward: %v", err) } }
func (self *channelAPI) Blob_Keep(perma grapher.PermaNode, permission grapher.PermissionNode, keep grapher.KeepNode) { mutJson := map[string]interface{}{"perma": perma.BlobRef(), "seq": keep.SequenceNumber(), "type": "keep", "signer": keep.Signer(), "mimetype": perma.MimeType()} if permission != nil { mutJson["permission"] = permission.SequenceNumber() } schema, err := json.Marshal(mutJson) if err != nil { panic(err.String()) } message := string(schema) if self.bufferOnly { self.messageBuffer = append(self.messageBuffer, string(schema)) } else { self.forwardToUser(keep.Signer(), message) err = self.forwardToFollowers(perma.BlobRef(), message) } if err != nil { log.Printf("Err Forward: %v", err) } }
func (self *channelAPI) Signal_ReceivedInvitation(perma grapher.PermaNode, permission grapher.PermissionNode) { // TODO: Compute digest var digest = "Untitled page" msgJson := map[string]interface{}{"perma": perma.BlobRef(), "type": "invitation", "signer": permission.Signer(), "permission": permission.BlobRef(), "digest": digest} fillInboxItem(self.store, perma.BlobRef(), int64(0), msgJson) schema, err := json.Marshal(msgJson) if err != nil { panic(err.String()) } if self.bufferOnly { self.messageBuffer = append(self.messageBuffer, string(schema)) } else { if perma.MimeType() == "application/x-lightwave-page" { addToInbox(self.c, permission.UserName(), perma.BlobRef(), 0) } err = self.forwardToUser(permission.UserName(), string(schema)) } if err != nil { log.Printf("Err Forward: %v", err) } // Automatically accept the invitation // self.grapher.CreateKeepBlob(perma.BlobRef(), permission.BlobRef()) }
func handleOpen(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) userid, sessionid, err := getSession(c, r) if err != nil { sendError(w, r, "No session cookie") return } // Read the request body jreq, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, "Error reading request body", http.StatusInternalServerError) return } r.Body.Close() // Parse request var req openCloseRequest err = json.Unmarshal(jreq, &req) if err != nil { sendError(w, r, "Malformed JSON") return } // Load the channel infos var ch channelStruct if err = datastore.Get(c, datastore.NewKey("channel", userid+"/"+sessionid, 0, nil), &ch); err != nil { sendError(w, r, "Unknown channel: "+userid+"/"+sessionid) return } // Check if len(ch.OpenPermas) >= 10 { sendError(w, r, "Too many open channels") return } is_open := false for _, p := range ch.OpenPermas { if p == req.Perma { is_open = true break } } var perma grapher.PermaNode if !is_open { // Update channel infos ch.OpenPermas = append(ch.OpenPermas, req.Perma) _, err = datastore.Put(c, datastore.NewKey("channel", userid+"/"+sessionid, 0, nil), &ch) if err != nil { sendError(w, r, "Internal server error") return } // Repeat all blobs from this document. s := newStore(c) g := grapher.NewGrapher(userid, schema, s, s, nil) s.SetGrapher(g) ch := newChannelAPI(c, s, userid, sessionid, true, g) perma, err = g.Repeat(req.Perma, req.From) if err != nil { sendError(w, r, "Failed opening") return } fmt.Fprintf(w, `{"ok":true, "blobs":[%v]}`, strings.Join(ch.messageBuffer, ",")) } else { fmt.Fprint(w, `{"ok":true, "blobs":[]}`) } if req.MarkAsRead { if perma == nil { s := newStore(c) data, err := s.GetPermaNode(req.Perma) if err != nil { log.Printf("Err: Failed reading permanode") return } perma = grapher.NewPermaNode(nil) perma.FromMap(req.Perma, data) } markAsRead(c, userid, perma.BlobRef(), perma.SequenceNumber()-1) } }
func (self *uniAPI) blob(perma grapher.PermaNode, blob grapher.OTNode) { log.Printf("API blob %v", blob.SequenceNumber()) self.mutex.Lock() // Is this perma blob opened? nextSeqNumber, ok := self.open[perma.BlobRef()] if !ok { // Is this a new keep of the local user? If yes, send it. Otherwise ignore it if keep, ok := blob.(grapher.KeepNode); ok && keep.Signer() == self.userID { self.mutex.Unlock() self.app.Signal_ProcessedKeep(perma, keep) return } self.mutex.Unlock() return } if nextSeqNumber > blob.SequenceNumber() { // Ignore this mutation. We have seen it already (should not happen anyway) self.mutex.Unlock() return } if nextSeqNumber < blob.SequenceNumber() { // Remember that we need to process these mutations later on, too, but not now q, ok := self.queues[perma.BlobRef()] if !ok || blob.SequenceNumber() < q { self.queues[perma.BlobRef()] = blob.SequenceNumber() } self.mutex.Unlock() return } // Store the next expected sequence number self.open[perma.BlobRef()] = blob.SequenceNumber() + 1 // Is there a need to continue with queued mutations? cont := int64(-1) j, ok := self.queues[perma.BlobRef()] if ok { cont = j self.queues[perma.BlobRef()] = 0, false } self.mutex.Unlock() // Notify the application self.app.Blob(perma, blob) // Ask to repeat further blobs in case we have already seen some if cont != -1 { self.grapher.Repeat(perma.BlobRef(), cont) } }