arnaucube
arnaucube/goCaptchaPublic Self-hosted repository
goCaptcha/serverRoutes.go
serverRoutes.goRaw
  1package main
  2
  3import (
  4	"encoding/json"
  5	"fmt"
  6	"image/jpeg"
  7	"io/ioutil"
  8	"log"
  9	"net/http"
 10	"strings"
 11	"time"
 12
 13	"gopkg.in/mgo.v2/bson"
 14
 15	"github.com/gorilla/mux"
 16)
 17
 18type Routes []Route
 19
 20var routes = Routes{
 21	Route{
 22		"Index",
 23		"GET",
 24		"/",
 25		Index,
 26	},
 27	Route{
 28		"GetImage",
 29		"GET",
 30		"/image/{imageName}",
 31		GetImage,
 32	},
 33	Route{
 34		"GetCaptcha",
 35		"GET",
 36		"/captcha",
 37		GetCaptcha,
 38	},
 39	Route{
 40		"AnswerCaptcha",
 41		"POST",
 42		"/answer",
 43		AnswerCaptcha,
 44	},
 45}
 46
 47//ROUTES
 48
 49func Index(w http.ResponseWriter, r *http.Request) {
 50	fmt.Fprintln(w, "ask for images in /r")
 51}
 52
 53func GetImage(w http.ResponseWriter, r *http.Request) {
 54	vars := mux.Vars(r)
 55	imageName := vars["imageName"]
 56
 57	imgFakePath := ImgFakePath{}
 58	err := imgFakePathCollection.Find(bson.M{"fake": imageName}).One(&imgFakePath)
 59	check(err)
 60
 61	file, err := ioutil.ReadFile(serverConfig.ImgsFolder + "/" + imgFakePath.Real)
 62	if err != nil {
 63		fmt.Fprintln(w, err)
 64	}
 65
 66	pathSplited := strings.Split(imgFakePath.Real, ".")
 67	imageExtension := pathSplited[len(pathSplited)-1]
 68	img, err := dataToImage(file, imageExtension)
 69
 70	if err != nil {
 71		fmt.Fprintln(w, "image "+imageName+" does not exist in server")
 72	} else {
 73		jpeg.Encode(w, img, nil) // Write to the ResponseWriter
 74	}
 75}
 76func GetCaptcha(w http.ResponseWriter, r *http.Request) {
 77
 78	ip := strings.Split(r.RemoteAddr, ":")[0]
 79	resp := generateCaptcha(serverConfig.NumImgsCaptcha, ip)
 80	jsonResp, err := json.Marshal(resp)
 81	check(err)
 82	fmt.Fprintln(w, string(jsonResp))
 83}
 84
 85func AnswerCaptcha(w http.ResponseWriter, r *http.Request) {
 86	decoder := json.NewDecoder(r.Body)
 87	var captchaAnswer CaptchaAnswer
 88	err := decoder.Decode(&captchaAnswer)
 89	check(err)
 90	defer r.Body.Close()
 91
 92	ip := strings.Split(r.RemoteAddr, ":")[0]
 93	resp := validateCaptcha(captchaAnswer, ip)
 94	//if resp==false add ip to blacklist
 95	if resp == false {
 96		//get SuspiciousIP
 97		suspiciousIP := SuspiciousIP{}
 98		err := suspiciousIPCollection.Find(bson.M{"ip": ip}).One(&suspiciousIP)
 99		if err != nil {
100			//if not exist, add
101			suspiciousIP.Date = time.Now().Unix()
102			suspiciousIP.IP = ip
103			suspiciousIP.Count = 0
104			//store suspiciousIP in MongoDB
105			err := suspiciousIPCollection.Insert(suspiciousIP)
106			check(err)
107		} else {
108			//if exist
109			suspiciousIP.Date = time.Now().Unix()
110			suspiciousIP.Count++
111			err := suspiciousIPCollection.Update(bson.M{"ip": ip}, suspiciousIP)
112			check(err)
113		}
114	}
115	//if count > limit, resp=false
116	suspiciousIP := SuspiciousIP{}
117	err = suspiciousIPCollection.Find(bson.M{"ip": ip}).One(&suspiciousIP)
118	if err == nil {
119		//if exist, and time.Since(suspiciousIP.Date) < serverConfig.TimeBan, increase counter
120		if time.Since(time.Unix(suspiciousIP.Date, 0)).Seconds() < serverConfig.TimeBan {
121			if suspiciousIP.Count > serverConfig.SuspiciousIPCountLimit {
122				if resp == false {
123					log.Println("IP: " + ip + ", has reached limit count of SuspiciousIP")
124				}
125				resp = false
126			}
127		} else {
128			//timeBan is completed, delete counter
129			err := suspiciousIPCollection.Remove(bson.M{"ip": ip})
130			check(err)
131		}
132		if resp == true {
133			//answered correct, delete counter
134			err := suspiciousIPCollection.Remove(bson.M{"ip": ip})
135			check(err)
136		}
137	}
138
139	jsonResp, err := json.Marshal(resp)
140	check(err)
141	fmt.Fprintln(w, string(jsonResp))
142}