// GetNode retrieves a single node from the database, removes // sensitive data (such as an email address) and sets ctx.Data to it. func (*Api) GetNode(ctx *jas.Context) { ip := IP(net.ParseIP(ctx.RequireString("address"))) if ip == nil { // If this is encountered, the address was incorrectly // formatted. ctx.Error = jas.NewRequestError("addressInvalid") return } node, err := Db.GetNode(ip) if err != nil { // If there has been a database error, log it and report the // failure. ctx.Error = jas.NewInternalError(err) l.Err(err) return } if node == nil { // If there are simply no matching nodes, set the error and // return. ctx.Error = jas.NewRequestError("No matching node") return } // Remove any sensitive data. node.OwnerEmail = "" // Finally, set the data and exit. ctx.Data = node }
func (*Weixin) Get(ctx *jas.Context) { fmt.Println("Get weixin") echostr := ctx.RequireString("echostr") nonce := ctx.RequireString("nonce") timestamp := ctx.RequireString("timestamp") sig := ctx.RequireString("signature") params := []string{nonce, timestamp, WEIXIN_TOKEN} sort.Sort(sort.StringSlice(params)) data := "" for _, v := range params { data += v } sha1Sig := string(sha1s(data)) ctx.Data = echostr if sig == sha1Sig { cfg := &jas.Config{} cfg.HijackWrite = func(writer io.Writer, ctx *jas.Context) int { len, _ := writer.Write([]byte(reflect.ValueOf(ctx.Data).String())) return len } // ctx.SetConfig(cfg) } }
func (*Sporocilo) Post(ctx *jas.Context) { nick := ctx.RequireString("nick") msg := ctx.RequireString("msg") title := ctx.RequireString("title") if nick != "" && msg != "" { err, res := sporocilo.ShraniSporocilo(nick, title, msg) if err == nil { b, _ := json.Marshal(res) log.Println(string(b)) Notify(string(b)) ctx.Data = res } } }
// PostNode creates a *Node from the submitted form and queues it for // addition. func (*Api) PostNode(ctx *jas.Context) { if Db.ReadOnly { // If the database is readonly, set that as the error and // return. ctx.Error = ReadOnlyError return } // Initialize the node and retrieve fields. node := new(Node) ip := IP(net.ParseIP(ctx.RequireString("address"))) if ip == nil { // If the address is invalid, return that error. ctx.Error = jas.NewRequestError("addressInvalid") return } node.Addr = ip node.Latitude = ctx.RequireFloat("latitude") node.Longitude = ctx.RequireFloat("longitude") node.OwnerName = ctx.RequireString("name") node.OwnerEmail = ctx.RequireString("email") status, _ := ctx.FindInt("status") node.Status = int(status) // TODO(DuoNoxSol): Authenticate/limit node registration. err := Db.AddNode(node) if err != nil { // If there was an error, log it and report the failure. ctx.Error = jas.NewInternalError(err) l.Err(err) return } ctx.Data = "successful" l.Infof("Node %q registered\n", ip) }
// PostUpdateNode removes a Node of a given IP from the database and // re-adds it with the supplied information. It is the equivalent of // removing a Node from the database, then invoking PostNode() with // its information, with the exception that it does not send a // verification email, and requires that the request be sent by the // Node that is being update. func (*Api) PostUpdateNode(ctx *jas.Context) { if Db.ReadOnly { // If the database is readonly, set that as the error and // return. ctx.Error = ReadOnlyError return } var err error // Require a token, because this is a very sensitive endpoint. RequireToken(ctx) // Retrieve the given IP address, check that it's sane, and check // that it exists in the *local* database. ip := IP(net.ParseIP(ctx.RequireStringLen(0, 40, "address"))) if ip == nil { // If the address is invalid, return that error. ctx.Error = jas.NewRequestError("addressInvalid") return } node, err := Db.GetNode(ip) if err != nil { ctx.Error = jas.NewInternalError(err.Error()) return } if node == nil || len(node.OwnerEmail) == 0 { ctx.Error = jas.NewRequestError("no matching local node") return } // Check to make sure that the Node is the one sending the // address, or an admin. If not, return an error. if !net.IP(ip).Equal(net.ParseIP(ctx.RemoteAddr)) && !IsAdmin(ctx.Request) { ctx.Error = jas.NewRequestError( RemoteAddressDoesNotMatchError.Error()) return } node.Addr = ip node.Latitude = ctx.RequireFloat("latitude") node.Longitude = ctx.RequireFloat("longitude") node.OwnerName = html.EscapeString(ctx.RequireString("name")) node.Contact, err = ctx.FindString("contact") if err != nil { ctx.Error = jas.NewRequestError("someError") return } node.Contact = html.EscapeString(node.Contact) node.Details, err = ctx.FindString("details") if err != nil { ctx.Error = jas.NewRequestError("someError") return } node.Details = html.EscapeString(node.Details) // If Contact, Details, or OwnerName are too long to fit in // the database, produce an error. if len(node.Contact) > 255 { ctx.Error = jas.NewRequestError("contactTooLong") return } if len(node.Details) > 255 { ctx.Error = jas.NewRequestError("detailsTooLong") return } if len(node.OwnerName) > 255 { ctx.Error = jas.NewRequestError("ownerNameTooLong") return } // Validate the PGP ID, if given. It can be an lowercase hex // string of length 0, 8, or 16. pgpstr, _ := ctx.FindStringMatch(PGPRegexp, "pgp") if node.PGP, err = DecodePGPID([]byte(pgpstr)); err != nil { ctx.Error = jas.NewRequestError("pgpInvalid") return } status, _ := ctx.FindPositiveInt("status") node.Status = uint32(status) // Note that we do not perform a verification step here, or send // an email. Because the Node was already verified once, we can // assume that it remains usable. // Update the Node in the database, replacing the one of matching // IP. err = Db.UpdateNode(node) if err != nil { ctx.Error = jas.NewInternalError(err) l.Errf("Error updating %q: %s", node.Addr, err) return } // If we reach this point, all was successful. ctx.Data = "successful" }
// PostNode creates a *Node from the submitted form and queues it for // addition with a positive 64 bit integer as an ID. func (*Api) PostNode(ctx *jas.Context) { if Db.ReadOnly { // If the database is readonly, set that as the error and // return. ctx.Error = ReadOnlyError return } var err error // Require a token, because this is mildly sensitive. RequireToken(ctx) // Initialize the node and retrieve fields. node := new(Node) ip := IP(net.ParseIP(ctx.RequireStringLen(0, 40, "address"))) if ip == nil { // If the address is invalid, return that error. ctx.Error = jas.NewRequestError("addressInvalid") return } node.Addr = ip node.Latitude = ctx.RequireFloat("latitude") node.Longitude = ctx.RequireFloat("longitude") node.OwnerName = html.EscapeString(ctx.RequireString("name")) node.OwnerEmail = ctx.RequireStringMatch(EmailRegexp, "email") node.Contact, _ = ctx.FindString("contact") node.Contact = html.EscapeString(node.Contact) node.Details, _ = ctx.FindString("details") node.Details = html.EscapeString(node.Details) // If Contact, Details, or OwnerName are too long to fit in // the database, produce an error. if len(node.Contact) > 255 { ctx.Error = jas.NewRequestError("contactTooLong") return } if len(node.Details) > 255 { ctx.Error = jas.NewRequestError("detailsTooLong") return } if len(node.OwnerName) > 255 { ctx.Error = jas.NewRequestError("ownerNameTooLong") return } // Validate the PGP ID, if given. It can be an lowercase hex // string of length 0, 8, or 16. pgpstr, _ := ctx.FindStringMatch(PGPRegexp, "pgp") if node.PGP, err = DecodePGPID([]byte(pgpstr)); err != nil { ctx.Error = jas.NewRequestError("pgpInvalid") return } status, _ := ctx.FindPositiveInt("status") node.Status = uint32(status) // Ensure that the node is correct and usable. if err = Db.VerifyRegistrant(node); err != nil { ctx.Error = jas.NewRequestError(err.Error()) return } // TODO(DuoNoxSol): Authenticate/limit node registration. // If SMTP is missing from the config, we cannot continue. if Conf.SMTP == nil { ctx.Error = jas.NewInternalError(SMTPDisabledError) l.Err(SMTPDisabledError) return } // If SMTP verification is not explicitly disabled, and the // connecting address is not an admin, send an email. if !Conf.SMTP.VerifyDisabled && !IsAdmin(ctx.Request) { id := rand.Int63() // Pseudo-random positive int64 emailsent := true if err := SendVerificationEmail(id, node.OwnerEmail); err != nil { // If the sending of the email fails, set the internal // error and log it, then set a bool so that email can be // resent. If email continues failing to send, it will // eventually expire and be removed from the database. ctx.Error = jas.NewInternalError(err) l.Err(err) emailsent = false // Note that we do *not* return here. } // Once we have attempted to send the email, queue the node // for verification. If the email has not been sent, it will // be recorded in the database. if err := Db.QueueNode(id, emailsent, Conf.VerificationExpiration, node); err != nil { // If there is a database failure, report it as an // internal error. ctx.Error = jas.NewInternalError(err) l.Err(err) return } // If the email could be sent successfully, report // it. Otherwise, report that it is in the queue, and the // email will be resent. if emailsent { ctx.Data = "verification email sent" l.Infof("Node %q entered, waiting for verification", ip) } else { ctx.Data = "verification email will be resent" l.Infof("Node %q entered, verification email will be resent", ip) } } else { err := Db.AddNode(node) if err != nil { // If there was an error, log it and report the failure. ctx.Error = jas.NewInternalError(err) l.Err(err) return } // Add the new node to the RSS feed. AddNodeToRSS(node, time.Now()) ctx.Data = "node registered" l.Infof("Node %q registered\n", ip) } }