package main

import (
	"crypto/sha256"
	"crypto/tls"
	"database/sql"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/dchest/uniuri"

	"github.com/dgrijalva/jwt-go"
	"github.com/labstack/echo"
)

type handler struct{}
type userInfo struct {
	Result struct {
		Result struct {
			Sshpubkeyfp      []string `json:"sshpubkeyfp"`
			HasKeytab        bool     `json:"has_keytab"`
			Ipasshpubkey     []string `json:"ipasshpubkey"`
			Cn               []string `json:"cn"`
			Krbcanonicalname []string `json:"krbcanonicalname"`
			Krbticketflags   []string `json:"krbticketflags"`
			MemberofGroup    []string `json:"memberof_group"`
			HasPassword      bool     `json:"has_password"`
			Homedirectory    []string `json:"homedirectory"`
			Nsaccountlock    bool     `json:"nsaccountlock"`
			UID              []string `json:"uid"`
			Title            []string `json:"title"`
			Loginshell       []string `json:"loginshell"`
			Uidnumber        []string `json:"uidnumber"`
			Preserved        bool     `json:"preserved"`
			Krbextradata     []struct {
				Base64 string `json:"__base64__"`
			} `json:"krbextradata"`
			Mail                     []string `json:"mail"`
			MemberofindirectHbacrule []string `json:"memberofindirect_hbacrule"`
			Dn                       string   `json:"dn"`
			Displayname              []string `json:"displayname"`
			Mepmanagedentry          []string `json:"mepmanagedentry"`
			Ipauniqueid              []string `json:"ipauniqueid"`
			Krbloginfailedcount      []string `json:"krbloginfailedcount"`
			Krbpwdpolicyreference    []string `json:"krbpwdpolicyreference"`
			Krbprincipalname         []string `json:"krbprincipalname"`
			Givenname                []string `json:"givenname"`
			Krblastadminunlock       []struct {
				Datetime string `json:"__datetime__"`
			} `json:"krblastadminunlock"`
			Krbpasswordexpiration []struct {
				Datetime string `json:"__datetime__"`
			} `json:"krbpasswordexpiration"`
			Krblastfailedauth []struct {
				Datetime string `json:"__datetime__"`
			} `json:"krblastfailedauth"`
			Objectclass      []string `json:"objectclass"`
			Gidnumber        []string `json:"gidnumber"`
			Gecos            []string `json:"gecos"`
			Sn               []string `json:"sn"`
			MemberofSudorule []string `json:"memberof_sudorule"`
			Krblastpwdchange []struct {
				Datetime string `json:"__datetime__"`
			} `json:"krblastpwdchange"`
			Initials []string `json:"initials"`
		} `json:"result"`
		Value   string      `json:"value"`
		Summary interface{} `json:"summary"`
	} `json:"result"`
	Version   string      `json:"version"`
	Error     interface{} `json:"error"`
	ID        int         `json:"id"`
	Principal string      `json:"principal"`
}
type ServiceList struct {
	TotalCount    string `json:"TotalCount,omitempty"`
	ActiveCount   string `json:"ActiveCount,omitempty"`
	ActiveVMCount string `json:"ActiveVMCount,omitempty"`
	TotalVMCount  string `json:"TotalVMCount,omitempty"`
}
type user_findResult struct {
	Error     interface{} `json:"error"`
	ID        int         `json:"id"`
	Principal string      `json:"principal"`
	Result    struct {
		Count  int `json:"count"`
		Result []struct {
			Dn               string   `json:"dn"`
			Gidnumber        []string `json:"gidnumber"`
			Givenname        []string `json:"givenname"`
			Homedirectory    []string `json:"homedirectory"`
			Krbcanonicalname []string `json:"krbcanonicalname"`
			Krbprincipalname []string `json:"krbprincipalname"`
			Loginshell       []string `json:"loginshell"`
			Mail             []string `json:"mail"`
			Nsaccountlock    bool     `json:"nsaccountlock"`
			Sn               []string `json:"sn"`
			Telephonenumber  []string `json:"telephonenumber"`
			UID              []string `json:"uid"`
			Uidnumber        []string `json:"uidnumber"`
		} `json:"result"`
		Summary   string `json:"summary"`
		Truncated bool   `json:"truncated"`
	} `json:"result"`
	Version string `json:"version"`
}
var User = userInfo{}

func (h *handler) login(c echo.Context) error {
	username := c.FormValue("username")
	password := c.FormValue("password")
	_url := URL + "/ipa/session/login_password"
	method := "POST"
	params := url.Values{}
	params.Add("user", username)
	params.Add("password", password)
	payload := strings.NewReader(params.Encode())
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest(method, _url, payload)
	audit("Recieved Login request from: " + RealIP)
	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("Referer", URL+"/ipa")
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Add("Accept", "text/plain")
	res, err := client.Do(req)
	cockie := res.Cookies()
	token := cockie[0].Raw
	ba := basicAuth(username, password)
	token = token + "Basic " + ba + ";"
	//fmt.Println("Token:", token)
	defer res.Body.Close()
	//fmt.Println(res.StatusCode)
	if res.StatusCode == 200 {
		User = getUserInfo(token, username)
		//fmt.Println(user.Result)
		tokens, err := generateTokenPair(User, token)
		if err != nil {
			return err
		}

		return c.JSON(http.StatusOK, tokens)
	}

	return echo.ErrUnauthorized
}
func getUserInfo(token string, username string) userInfo {
	//fmt.Println("Checking for User: ", username)
	url := URL + "/ipa/session/json"
	method := "POST"
	_json := fmt.Sprintf(`
{
    "method": "user_show",
    "params": [
        [
            "%s"
        ],
        {
            "all": true,
            "version": "2.215"
        }
    ],
    "id": 0
}
`, username)

	payload := strings.NewReader(_json)
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("Referer", URL+"/ipa")
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Accept", "text/plain")
	req.Header.Add("Cookie", token)
	res, err := client.Do(req)
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	//fmt.Println("Getting Data for Response: ", body)
	user := userInfo{}
	json.Unmarshal(body, &user)
	//fmt.Println("Getting Data for User: ", user.Result.Result.Uidnumber)
	return user
}
func (h *handler) uuidgen(c echo.Context) error {
	resource := c.FormValue("resource")
	id, code := uuidgen(resource)

	resp := _response{
		Origin:  "uuidgen",
		Message: id,
		Code:    code,
	}
	//b, _ := json.MarshalIndent(resp, "", "  ")
	//return c.String(http.StatusOK, string(b))
	return c.JSON(http.StatusOK, resp)
}
func (h *handler) addUser(c echo.Context) error {
	type apiErr struct {
		Result interface{} `json:"result"`
		Error  struct {
			Code    int    `json:"code"`
			Message string `json:"message"`
			Data    struct {
			} `json:"data"`
			Name string `json:"name"`
		} `json:"error"`
		ID        int    `json:"id"`
		Principal string `json:"principal"`
		Version   string `json:"version"`
	}
	type addUser struct {
		Result struct {
			Result struct {
				Displayname           []string `json:"displayname"`
				UID                   []string `json:"uid"`
				Uidnumber             []string `json:"uidnumber"`
				Objectclass           []string `json:"objectclass"`
				Sn                    []string `json:"sn"`
				Telephonenumber       []string `json:"telephonenumber"`
				Cn                    []string `json:"cn"`
				Krbpasswordexpiration []struct {
					Datetime string `json:"__datetime__"`
				} `json:"krbpasswordexpiration"`
				Mobile           []string `json:"mobile"`
				Krbprincipalname []string `json:"krbprincipalname"`
				Ipauniqueid      []string `json:"ipauniqueid"`
				Givenname        []string `json:"givenname"`
				Gidnumber        []string `json:"gidnumber"`
				Krbcanonicalname []string `json:"krbcanonicalname"`
				Mail             []string `json:"mail"`
				Initials         []string `json:"initials"`
				Homedirectory    []string `json:"homedirectory"`
				Loginshell       []string `json:"loginshell"`
				Gecos            []string `json:"gecos"`
				Randompassword   string   `json:"randompassword"`
				HasPassword      bool     `json:"has_password"`
				HasKeytab        bool     `json:"has_keytab"`
				MemberofGroup    []string `json:"memberof_group"`
				Dn               string   `json:"dn"`
			} `json:"result"`
			Value   string `json:"value"`
			Summary string `json:"summary"`
		} `json:"result"`
		Error     string `json:"error"`
		ID        int    `json:"id"`
		Principal string `json:"principal"`
		Version   string `json:"version"`
	}
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	b, err := json.Marshal(claims)
	if err != nil {
		fmt.Println("err:", err)
	}
	//fmt.Println("AddUser Claims: ", claims)
	//fmt.Println("AddUser token: ", token)
	username := c.FormValue("Username")
	sha256 := sha256.Sum256([]byte(username))
	var hashChannel = make(chan []byte, 1)
	hashChannel <- sha256[:]
	ciphertext := encrypt(<-hashChannel, string(b))
	//fmt.Println("B: ", string(b))
	//fmt.Println("Ciphere: ", ciphertext)
	sn := c.FormValue("Lname")
	cn := c.FormValue("FullName")
	givenname := c.FormValue("Fname")
	displayname := c.FormValue("displayname")
	krbpasswordexpiration := c.FormValue("krbpasswordexpiration")
	mail := c.FormValue("mail")
	telephonenumber := c.FormValue("telephonenumber")
	mobile := c.FormValue("mobile")
	_url := URL + "/ipa/session/json"
	method := "POST"
	_json := fmt.Sprintf(`
{
    "id": 0,
    "method": "user_add/1",
    "params": [
        [
            "%s"
        ],
        {
            "givenname": "%s",
            "sn": "%s",
            "cn":"%s",
            "displayname":"%s",
            "loginshell":"/usr/sbin/nologin",
            "krbpasswordexpiration":"%s",
            "mail":"%s",
            "random":"true",
            "gidnumber":"599200001",
            "telephonenumber":"%s",
            "mobile":"%s",
            "version": "2.235"
        }
    ]
}
`, username, givenname, sn, cn, displayname, krbpasswordexpiration, mail, telephonenumber, mobile)
	__json := fmt.Sprintf(`
{
    "id": 0,
    "method": "group_add_member/1",
    "params": [
        [
            "svcaccounts"
        ],
        {
            "user": [
                "%s"
            ],
            "version": "2.235"
        }
    ]
}
`, username)
	payload := strings.NewReader(_json)
	_payload := strings.NewReader(__json)
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest(method, _url, payload)
	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("Referer", URL+"/ipa")
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Accept", "text/plain")
	req.Header.Add("Cookie", token)
	res, err := client.Do(req)
	_req, _ := http.NewRequest(method, _url, _payload)
	_req.Header.Add("Referer", URL+"/ipa")
	_req.Header.Add("Content-Type", "application/json")
	_req.Header.Add("Accept", "text/plain")
	_req.Header.Add("Cookie", token)
	client.Do(_req)
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	result := addUser{}
	_err := json.Unmarshal(body, &result)
	//	fmt.Println(result)
	if _err != nil {
		_apiErr := apiErr{}
		__err := json.Unmarshal(body, &_apiErr)
		if __err != nil {
			return c.String(http.StatusBadRequest, "Error of error!!")
		}
		//res2B, _ := json.Marshal(_apiErr)
		//return c.String(http.StatusBadRequest, string(res2B))
		resp := _response{
			Origin:  "AddUser",
			Message: _apiErr.Error.Name + ": " + _apiErr.Error.Message,
			Code:    _apiErr.Error.Code,
		}
		return c.JSON(http.StatusNotFound, resp)
		//return c.JSON(http.StatusBadRequest, _apiErr)
	}
	shortLink := setResetKey(ciphertext, username)
	go sendMail("Welcome to ZiCloud\r\n Your temporary link is :\r\n http://zi-cloud.ir/reset/"+url.QueryEscape(shortLink), "Welcome to ZiCloud", mail)
	//go sendMail("Welcome to ZiCloud\r\n Your temporary link is :\r\n https://zicloud.com/reset/"+url.QueryEscape(ciphertext), "Welcome to ZiCloud", mail)
	resp := _response{
		Origin:  "addUser",
		Message: "Done, Reset Link was sent to your email",
		Code:    1000,
	}
	//b, _ = json.MarshalIndent(resp, "", "  ")
	//return c.String(http.StatusOK, string(b))
	return c.JSON(http.StatusOK, resp)
}
func (h *handler) disableUser(c echo.Context) error {
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	username := c.FormValue("Username")
	url := URL + "/ipa/session/json"
	method := "POST"
	_json := fmt.Sprintf(`
{
    "id": 0,
    "method": "user_disable/1",
    "params": [
        [
            "%s"
        ],
        {
            "version": "2.235"
        }
    ]
}
`, username)
	payload := strings.NewReader(_json)
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest(method, url, payload)
	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("Referer", URL+"/ipa")
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Accept", "text/plain")
	req.Header.Add("Cookie", token)
	res, err := client.Do(req)
	if err != nil {
		//return c.String(http.StatusBadRequest, "Error"+err.Error())
		return c.JSON(http.StatusOK, "Error"+err.Error())
	}
	defer res.Body.Close()
	resp := _response{
		Origin:  "disableUser",
		Message: "Done",
		Code:    1000,
	}
	//b, _ := json.MarshalIndent(resp, "", "  ")
	return c.JSON(http.StatusOK, resp)
	//return c.String(http.StatusOK, string(b))
}
func (h *handler) resetUser(c echo.Context) error {
	type keyJson struct {
		IPAToken string   `json:"IPAToken"`
		Admin    bool     `json:"admin"`
		Exp      int      `json:"exp"`
		Memberof []string `json:"memberof"`
		Name     string   `json:"name"`
		Sub      int      `json:"sub"`
	}
	t := time.Now() //%Y%m%d%H%M%SZ
	t = t.Add(time.Hour * 24 * 60)
	//username := c.FormValue("Username")
	password := c.FormValue("Password")
	short := c.FormValue("key")
	key, username := getResetKey(short)
	if len(key) < 5 {
		resp := _response{
			Origin:  "resetUser",
			Message: "Link has been expired",
			Code:    1001,
		}
		//b, _ := json.MarshalIndent(resp, "", "  ")
		return c.JSON(http.StatusOK, resp)
	}
	//key, _ = url.QueryUnescape(key)
	_sha256 := sha256.Sum256([]byte(username))
	var hashChannel = make(chan []byte, 1)
	hashChannel <- _sha256[:]
	plainkey := decrypt(<-hashChannel, key)
	_plainkey := keyJson{}
	json.Unmarshal([]byte(plainkey), &_plainkey)
	_name := _plainkey.Name
	//_sha256 := sha256.Sum256([]byte(string("")))
	var hashChannel_ = make(chan []byte, 1)
	__sha256 := sha256.Sum256([]byte(_name))
	hashChannel_ <- __sha256[:]
	token := decrypt(<-hashChannel_, string(_plainkey.IPAToken))
	//	token := _plainkey.IPAToken
	_url := URL + "/ipa/session/json"
	method := "POST"
	_json := fmt.Sprintf(`
{
    "id": 0,
    "method": "user_mod/1",
    "params": [
        [
            "%s"
        ],
        {
			"userpassword":"%s",
            "version": "2.235"
        }
    ]
}
`, username, password)
	payload := strings.NewReader(_json)
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest(method, _url, payload)
	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("Referer", URL+"/ipa")
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Accept", "text/plain")
	req.Header.Add("Cookie", token)
	res, err := client.Do(req)
	//fmt.Println(token)
	//fmt.Println(_json)
	//fmt.Println(req)
	//fmt.Println(res)
	_json = fmt.Sprintf(`
{
    "id": 0,
    "method": "user_mod/1",
    "params": [
        [
            "%s"
        ],
        {
            "krbpasswordexpiration":"%s",
            "version": "2.235"
        }
    ]
}
`, username, t.Format("2006-01-02")+"Z")
	payload = strings.NewReader(_json)
	req, err = http.NewRequest(method, _url, payload)
	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("Referer", URL+"/ipa")
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Accept", "text/plain")
	req.Header.Add("Cookie", token)
	err = nil
	res, err = client.Do(req)
	//fmt.Println(token)
	//fmt.Println(_json)
	//fmt.Println(req)
	//fmt.Println(res)
	if err != nil {
		//return c.String(http.StatusBadRequest, "Error"+err.Error())
		return c.JSON(http.StatusBadRequest, "Error"+err.Error())
	}
	defer res.Body.Close()
	resp := _response{
		Origin:  "resetUser",
		Message: "Done",
		Code:    1000,
	}
	expireResetKey(username)
	//b, _ := json.MarshalIndent(resp, "", "  ")
	return c.JSON(http.StatusOK, resp)
	//return c.String(http.StatusOK, string(b))
}
func (h *handler) dnsrecordadd(c echo.Context) error {
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	recordName := c.FormValue("recordName")
	record := c.FormValue("record")
	url := URL + "/ipa/session/json"
	method := "POST"
	_json := fmt.Sprintf(`
{
    "id": 0,
    "method": "dnsrecord_add/1",
    "params": [
        [
            "ZI-TEL.COM",
            {
                "__dns_name__": "%s"
            }
        ],
        {
            "a_part_ip_address": "%s",
            "raw": true,
            "version": "2.235"
        }
    ]
}
`, recordName, record)
	payload := strings.NewReader(_json)
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest(method, url, payload)
	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("Referer", URL+"/ipa")
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Accept", "text/plain")
	req.Header.Add("Cookie", token)
	res, err := client.Do(req)
	if err != nil {
		//return c.String(http.StatusBadRequest, "Error"+err.Error())
		return c.JSON(http.StatusBadRequest, "Error"+err.Error())
	}
	//body, err := ioutil.ReadAll(res.Body)
	//_res:=result{}
	//json.Unmarshal(body, &_res)
	//fmt.Println(_res)
	defer res.Body.Close()
	resp := _response{
		Origin:  "dnsrecordadd",
		Message: "Done",
		Code:    1000,
	}
	//b, _ := json.MarshalIndent(resp, "", "  ")
	return c.JSON(http.StatusOK, resp)
	//return c.String(http.StatusOK, string(b))
}
func (h *handler) token(c echo.Context) error {
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	username := claims["name"].(string)
	//fmt.Println("User: ",username)
	//fmt.Println("Token : ",token)
	_user := getUserInfo(token, username)
	//fmt.Println(_user.Result)
	newtokens, err := generateTokenPair(_user, token)
	if err != nil {
		return err
	}
	return c.JSON(http.StatusOK, newtokens)
}
func (h *handler) verifyUser(c echo.Context) error {
	name := c.FormValue("Username")
	//fmt.Println("Name: ", name)
	if name == "" {
		return c.JSON(http.StatusNotFound, "User NOT Found")
	}
	username := "admin"
	password := "h?_QJp5^&9FNc9w="
	_url := URL + "/ipa/session/login_password"
	method := "POST"
	params := url.Values{}
	params.Add("user", username)
	params.Add("password", password)
	payload := strings.NewReader(params.Encode())
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest(method, _url, payload)
	audit("Recieved Login request from: " + RealIP)
	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("Referer", URL+"/ipa")
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Add("Accept", "text/plain")
	res, err := client.Do(req)
	cockie := res.Cookies()
	token := cockie[0].Raw
	defer res.Body.Close()
	//fmt.Println(token)
	if res.StatusCode == 200 {
		user := getUserInfo(token, name)
		if user.Result.Value != name {
			resp := _response{
				Origin:  "VerifyUser",
				Message: "User Not Found",
				Code:    1000,
			}
			//b, _errr := json.MarshalIndent(resp, "", "  ")
			//b, _= json.Marshal(resp)
			//if _errr != nil {
			//	fmt.Println(_errr)
			//}
			//fmt.Print(string(b))
			return c.JSON(http.StatusOK, resp)
		}
	}
	resp := _response{
		Origin:  "VerifyUser",
		Message: "User Found",
		Code:    1001,
	}
	//b, _ := json.MarshalIndent(resp, "", "  ")

	return c.JSON(http.StatusNotFound, resp)
}
func (h *handler) forgetpassword(c echo.Context) error {

	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	_type := c.FormValue("type")
	_data := c.FormValue("data")
	url := URL + "/ipa/session/json"
	method := "POST"
	__type, _ := strconv.Atoi(_type)
	_json := ""
	if __type == 1 {
		// email
		_json = fmt.Sprintf(`
{
  "id": 0,
    "method": "user_find/1",
    "params": [
        [],
        {
            "mail": [
                "%s"
            ],
            "version": "2.235"
        }
    ]
}
`, _data)
	} else if __type == 2 {
		// username
		_json = fmt.Sprintf(`
{
  "id": 0,
    "method": "user_find/1",
    "params": [
        [
            "%s"
        ],
        {
            "version": "2.235"
        }
    ]
}
`, _data)
	} else if __type == 3 {
		//mobile
		_json = fmt.Sprintf(`
{
    "id": 0,
    "method": "user_find/1",
    "params": [
        [],
        {
            "mobile": [
                "%s"
            ],
            "version": "2.235"
        }
    ]
}
`, _data)

	} else {
		resp := _response{
			Origin:  "forgetpassword",
			Message: "unknown requested type",
			Code:    1001,
		}
		return c.JSON(http.StatusNotFound, resp)
	}
	//fmt.Println(_json)
	payload := strings.NewReader(_json)
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("Referer", URL+"/ipa")
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Accept", "text/plain")
	req.Header.Add("Cookie", token)
	res, err := client.Do(req)
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	//fmt.Println("Getting Data for Response: ", body)
	_user := user_findResult{}
	json.Unmarshal(body, &_user)
	fmt.Println("find in forgetpass : ", _user.Result.Count)
	if _user.Result.Count != 1 {
		resp := _response{
			Origin:  "forgetpassword",
			Message: "Something goes wrong",
			Code:    1001,
		}
		return c.JSON(http.StatusNotFound, resp)
	}
	b, err := json.Marshal(claims)
	if err != nil {
		fmt.Println("err:", err)
	}
	//fmt.Println("AddUser Claims: ", claims)
	//fmt.Println("AddUser token: ", token)
	username := _user.Result.Result[0].UID[0]
	sha256 := sha256.Sum256([]byte(username))
	var hashChannel = make(chan []byte, 1)
	hashChannel <- sha256[:]
	ciphertext := encrypt(<-hashChannel, string(b))
	shortLink := setResetKey(ciphertext, username)
	key, _ := getResetKey(username)
	if len(key) > 5 {
		resp := _response{
			Origin:  "forgetpassword",
			Message: "A resetLink request with this email already exists",
			Code:    1003,
		}
		return c.JSON(http.StatusNotFound, resp)
	}
	go sendMail("Your temporary link is :\r\n https://zicloud.com/reset/"+shortLink, "ResetPassword Link", _user.Result.Result[0].Mail[0])

	resp := _response{
		Origin:  "forgetpassword",
		Message: "You will receive an email with a link to reset your password",
		Code:    1000,
	}
	return c.JSON(http.StatusNotFound, resp)
}
func setResetKey(key string, username string) string {
	short := uniuri.NewLen(32)
	db, err := sql.Open("mysql", MySQLUSER+":"+MySQLPASS+"@tcp(127.0.0.1:3306)/zicloud")
	if err != nil {
		return ""
	}
	defer db.Close()
	insert, err := db.Query("INSERT INTO url_shortener VALUES ( '" + short + "'," +
		"'" + key + "'," +
		"NOW() + INTERVAL 1 HOUR" + "," +
		"'" + "setResetKey" + "'," +
		"'" + username + "'," +
		"1" +
		" )")
	defer insert.Close()
	return short
}
func getResetKey(short string) (string, string) {
	db, _ := sql.Open("mysql", MySQLUSER+":"+MySQLPASS+"@tcp(127.0.0.1:3306)/zicloud")
	results, _ := db.Query("SELECT `long` as `long`, related_obj as username FROM url_shortener where active=1 and short='" + short + "' and expiration > NOW()")
	var key, username string
	for results.Next() {
		err := results.Scan(&key, &username)
		if err != nil {
			return "ERR", "ERR"
		}
	}

	return key, username
}
func expireResetKey(username string) {
	db, err := sql.Open("mysql", MySQLUSER+":"+MySQLPASS+"@tcp(127.0.0.1:3306)/zicloud")
	if err != nil {
		return
	}
	update, err := db.Query("update url_shortener set active='0' where related_obj='" + username + "'")
	defer db.Close()
	defer update.Close()

}
func (h *handler) ListServices(c echo.Context) error {
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	//IPAUid:=claims["IPAUid"]
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	_BA := strings.Split(token, ";")
	BA := _BA[len(_BA)-2]
	db, _ := sql.Open("mysql", MySQLUSER+":"+MySQLPASS+"@tcp(127.0.0.1:3306)/zicloud")
	results, _ := db.Query("SELECT `type` as `type`, uuid as Service_uuid , active , objectName FROM service_profile where uid=" + claims["IPAUid"].(string))
	activeCount := 0
	totalCount := 0
	activeVMCount := 0
	totalVMCount := 0
	var cpu, mem float64
	var _type, service_uuid, active, objectName string
	for results.Next() {
		err := results.Scan(&_type, &service_uuid, &active, &objectName)
		if err != nil {
			resp := _response{
				Origin:  "ListServices",
				Message: "Listing Error",
				Code:    1001,
			}
			//b, _ := json.MarshalIndent(resp, "", "  ")
			return c.JSON(http.StatusOK, resp)
		}
		if _type == "VM" {
			if active == "1" {
				activeCount++
				activeVMCount++
				//fmt.Println(vmStatistics(BA,service_uuid))
				_, _cpu, _mem := vmStatistics(BA, service_uuid)
				cpu += _cpu
				mem += _mem
			}
			totalCount++
			totalVMCount++
		}
	}
	//fmt.Println(activeVMCount)
	//fmt.Println(activeCount)
	//fmt.Println(totalCount)
	//fmt.Println(totalVMCount)
	//SL := ServiceList{
	//	TotalCount:    string(totalCount),
	//	ActiveCount:   string(activeCount),
	//	ActiveVMCount: string(activeVMCount),
	//	TotalVMCount:  string(totalVMCount),
	//}
	type AutoGenerated struct {
		Message struct {
			TotalCount    string `json:"TotalCount"`
			ActiveCount   string `json:"ActiveCount"`
			ActiveVMCount string `json:"ActiveVMCount"`
			TotalVMCount  string `json:"TotalVMCount"`
			TotalCPUUsage string `json:"TotalCPUUsage"`
			TotalMemUsage string `json:"TotalMemUsage"`
		} `json:"message"`
		Origin string `json:"origin"`
		Code   int    `json:"code"`
	}
	resp := AutoGenerated{
		Message: struct {
			TotalCount    string `json:"TotalCount"`
			ActiveCount   string `json:"ActiveCount"`
			ActiveVMCount string `json:"ActiveVMCount"`
			TotalVMCount  string `json:"TotalVMCount"`
			TotalCPUUsage string `json:"TotalCPUUsage"`
			TotalMemUsage string `json:"TotalMemUsage"`
		}{
			TotalCount:    strconv.Itoa(totalCount),
			ActiveCount:   strconv.Itoa(activeCount),
			ActiveVMCount: strconv.Itoa(activeVMCount),
			TotalVMCount:  strconv.Itoa(totalVMCount),
			TotalCPUUsage: fmt.Sprintf("%f", 100*cpu/float64(activeVMCount)),
			TotalMemUsage: fmt.Sprintf("%f", 100*mem/float64(activeVMCount)),
		},
		Origin: "ListServices",
		Code:   1000,
	}
	return c.JSON(http.StatusOK, resp)
}
func (h *handler) PriceCalc(c echo.Context) error {
	user := c.Get("user").(*jwt.Token)
	db, _:= sql.Open("mysql", MySQLUSER+":"+MySQLPASS+"@tcp(127.0.0.1:3306)/zicloud")
	_, _ = db.Query("SELECT uuid as UUID ,task_apiCall as TaskAPICall , cron_expression as CronExpression , related_uuid as Ruuid, type FROM scheduler where active=1")
	_, _ = db.Query("SELECT uuid as UUID ,task_apiCall as TaskAPICall , cron_expression as CronExpression , related_uuid as Ruuid, type FROM scheduler where active=1")
	_, _ = db.Query("SELECT uuid as UUID ,task_apiCall as TaskAPICall , cron_expression as CronExpression , related_uuid as Ruuid, type FROM scheduler where active=1")
	db.Close()
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	//token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	cpu, _ := strconv.Atoi(c.FormValue("cpu"))
	mem, _ := strconv.Atoi(c.FormValue("mem"))
	hdd, _ := strconv.Atoi(c.FormValue("hdd"))
	nic, _ := strconv.Atoi(c.FormValue("nic"))
	period, _ := strconv.Atoi(c.FormValue("period"))
	type PriceCalculator struct {
		Data struct {
			TotalPrice string `json:"TotalPrice"`
		} `json:"message"`
		Origin string `json:"origin"`
		Code   int    `json:"code"`
	}
	resp := PriceCalculator{
		Data: struct {
			TotalPrice string `json:"TotalPrice"`
		}{TotalPrice: strconv.Itoa((cpu*500 + mem + 10 + hdd*19 + nic*10000)*period)},
		Origin: "PriceCalc",
		Code:   1000,
	}
	return c.JSON(http.StatusOK, resp)
}
