├── .DS_Store ├── .gitignore ├── README.md ├── conf └── app.conf ├── controllers ├── airad.go ├── base.go ├── common.go ├── default.go ├── device.go ├── error.go ├── mqtt.go ├── mqttoption.go ├── object.go └── user.go ├── database └── airad.sql ├── logs └── logs.log ├── main.go ├── models ├── airad.go ├── base.go ├── common.go ├── device.go ├── messages.go ├── mqtt.go ├── mqttoption.go ├── object.go └── user.go ├── pictures ├── airad.png └── airad_swagger.png ├── routers └── router.go ├── swagger ├── favicon-16x16.png ├── favicon-32x32.png ├── index.html ├── oauth2-redirect.html ├── swagger-ui-bundle.js ├── swagger-ui-bundle.js.map ├── swagger-ui-standalone-preset.js ├── swagger-ui-standalone-preset.js.map ├── swagger-ui.css ├── swagger-ui.css.map ├── swagger-ui.js ├── swagger-ui.js.map ├── swagger.json └── swagger.yml ├── tests └── default_test.go ├── utils ├── airad.go ├── bootStrap.go ├── cache.go ├── cropper.go ├── date.go ├── encrypt.go ├── hashUtils.go ├── jwt.go ├── rand.go ├── sql.go ├── template.go └── validator.go └── views └── index.tpl /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubinliudongpo/airad/3968aa1f7cefb098976544aa463db6535204f15a/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | routers/commentsRouter* 3 | airad 4 | lastupdate.tmp 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AirAd 2 | Beego based RestFul API service 3 | 4 | which supports mobile app as cloud service 5 |  6 | 7 | ## 特性 8 | 9 | - RestFul API 10 | - Access Token, User Auth 11 | 12 | ## 依赖 13 | 14 | - [github.com/astaxie/beego](https://github.com/astaxie/beego) 15 | - [github.com/astaxie/beego/context](https://github.com/astaxie/beego/context) 16 | - [github.com/astaxie/beego/orm](https://github.com/astaxie/beego/orm) 17 | - [github.com/dgrijalva/jwt-go](https://github.com/dgrijalva/jwt-go) 18 | - [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) 19 | 20 | 21 | ## 如何开始 22 | 23 | - 安装 [bee](https://github.com/beego/bee) 工具 24 | - go get github.com/rubinliudongpo/airad (注意配置GOROOT,GOPATH,详情请参考 http://sourabhbajaj.com/mac-setup/Go/README.html ) 25 | - 在mysql数据库里创建数据库名字叫airad 26 | ``` 27 | mysql -uroot -pYOURROOTPASSWORD -h 127.0.0.1 -e "CREATE DATABASE IF NOT EXISTS airad DEFAULT CHARSET utf8 COLLATE utf8_general_ci;" 28 | ``` 29 | - 创建(并授权给)用户(gouser)和密码(gopassword) 30 | ``` 31 | mysql -uroot -pYOURROOTPASSWORD -h 127.0.0.1 -e "grant all privileges on airad.* to gouser@'%' identified by 'gopass';" 32 | ``` 33 | - 导入airad.sql 34 | ``` 35 | mysql -uroot -pROOTPASSWORD airad < database/airad.sql 36 | ``` 37 | 38 | ## 查看和调试 39 | 40 | 请通过 http://localhost:9080/swagger/ 试用API,界面如下 41 |  42 | 43 | ## 注意 44 | - SWagger的路由页面待更新 45 | -------------------------------------------------------------------------------- /conf/app.conf: -------------------------------------------------------------------------------- 1 | appname = airad 2 | httpport = 9080 3 | runmode = dev 4 | autorender = false 5 | copyrequestbody = true 6 | EnableDocs = true 7 | Graceful = true 8 | 9 | db.host = 127.0.0.1 10 | db.port = 3306 11 | db.user = gouser 12 | db.password = gopass 13 | db.name = airad 14 | db.charset = utf8mb4 15 | 16 | sessionon = true 17 | sessionprovider = file 18 | sessionproviderconfig = "./tmp" 19 | sessiongcmaxlifetime = 31536000 20 | sessioncookielifetime = 31536000 21 | 22 | cache = redis 23 | redis_host = "127.0.0.1:6379" 24 | redis_password = "12345GESAFsfdtewS4G6789" 25 | cache_expire = 6000 26 | 27 | token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 28 | -------------------------------------------------------------------------------- /controllers/airad.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | //"github.com/astaxie/beego" 5 | "github.com/rubinliudongpo/airad/models" 6 | "strings" 7 | "errors" 8 | "encoding/json" 9 | "strconv" 10 | "github.com/rubinliudongpo/airad/utils" 11 | "fmt" 12 | ) 13 | 14 | // AirAdController operations for AirAd 15 | type AirAdController struct { 16 | BaseController 17 | } 18 | 19 | // URLMapping ... 20 | func (c *AirAdController) URLMapping() { 21 | c.Mapping("Post", c.Post) 22 | c.Mapping("GetOne", c.GetOne) 23 | c.Mapping("GetAll", c.GetAll) 24 | c.Mapping("Put", c.Put) 25 | c.Mapping("Delete", c.Delete) 26 | } 27 | 28 | // Post ... 29 | // @Title Create 30 | // @Description create AirAd 31 | // @Param body body models.AirAd true "body for AirAd content" 32 | // @Success 201 {object} models.AirAd 33 | // @Failure 403 body is empty 34 | // @router / [post] 35 | func (c *AirAdController) Post() { 36 | var v models.AirAd 37 | 38 | token := c.Ctx.Input.Header("token") 39 | //id := c.Ctx.Input.Header("id") 40 | et := utils.EasyToken{} 41 | //token := strings.TrimSpace(c.Ctx.Request.Header.Get("Authorization")) 42 | valido, err := et.ValidateToken(token) 43 | if !valido { 44 | c.Ctx.ResponseWriter.WriteHeader(401) 45 | c.Data["json"] = Response{401, 401, fmt.Sprintf("%s", err), ""} 46 | c.ServeJSON() 47 | return 48 | } 49 | if err := json.Unmarshal(c.Ctx.Input.RequestBody, &v); err == nil { 50 | if errorMessage := utils.CheckNewAirAdPost(v.DeviceId, v.Co, v.Humidity, v.Temperature, 51 | v.Pm25, v.Pm10, v.Nh3, v.O3, v.Suggest, v.AqiQuality); errorMessage != "ok"{ 52 | c.Ctx.ResponseWriter.WriteHeader(403) 53 | c.Data["json"] = Response{403, 403,errorMessage, ""} 54 | c.ServeJSON() 55 | return 56 | } 57 | if !models.CheckDeviceId(v.DeviceId){ 58 | c.Ctx.ResponseWriter.WriteHeader(403) 59 | c.Data["json"] = Response{403, 403,"设备Id不存在", ""} 60 | c.ServeJSON() 61 | return 62 | } 63 | 64 | if !models.CheckDeviceIdAndToken(v.DeviceId, token){ 65 | c.Ctx.ResponseWriter.WriteHeader(403) 66 | c.Data["json"] = Response{403, 403,"用户ID和Token不匹配", ""} 67 | c.ServeJSON() 68 | return 69 | } 70 | 71 | 72 | if airAdId, err := models.AddAirAd(&v); err == nil { 73 | if device, err := models.GetDeviceById(v.DeviceId); err == nil { 74 | models.UpdateDeviceAirAdCount(device) 75 | c.Ctx.Output.SetStatus(201) 76 | var returnData = &CreateObjectData{int(airAdId)} 77 | c.Data["json"] = &Response{0, 0, "ok", returnData} 78 | } else { 79 | c.Ctx.ResponseWriter.WriteHeader(403) 80 | c.Data["json"] = Response{403, 403,"设备Id不存在", ""} 81 | c.ServeJSON() 82 | return 83 | } 84 | 85 | } else { 86 | c.Data["json"] = err.Error() 87 | } 88 | } else { 89 | c.Data["json"] = err.Error() 90 | } 91 | c.ServeJSON() 92 | } 93 | 94 | // GetOne ... 95 | // @Title GetOne 96 | // @Description get AirAd by id 97 | // @Param id path string true "The key for static block" 98 | // @Success 200 {object} models.AirAd 99 | // @Failure 403 :id is empty 100 | // @router /:id [get] 101 | func (c *AirAdController) GetOne() { 102 | idStr := c.Ctx.Input.Param(":id") 103 | id, _ := strconv.Atoi(idStr) 104 | v, err := models.GetAirAdById(id) 105 | if err != nil { 106 | c.Data["json"] = err.Error() 107 | } else { 108 | c.Data["json"] = v 109 | } 110 | c.ServeJSON() 111 | 112 | } 113 | 114 | // GetAll ... 115 | // @Title GetAll 116 | // @Description get AirAd 117 | // @Param query query string false "Filter. e.g. col1:v1,col2:v2 ..." 118 | // @Param fields query string false "Fields returned. e.g. col1,col2 ..." 119 | // @Param sortby query string false "Sorted-by fields. e.g. col1,col2 ..." 120 | // @Param order query string false "Order corresponding to each sortby field, if single value, apply to all sortby fields. e.g. desc,asc ..." 121 | // @Param limit query string false "Limit the size of result set. Must be an integer" 122 | // @Param offset query string false "Start position of result set. Must be an integer" 123 | // @Success 200 {object} models.AirAd 124 | // @Failure 403 125 | // @router / [get] 126 | func (c *AirAdController) GetAll() { 127 | var fields []string 128 | var sortby []string 129 | var order []string 130 | var query = make(map[string]string) 131 | var limit int = 20 132 | var offset int 133 | var deviceId int 134 | 135 | deviceId, err := strconv.Atoi(c.Ctx.Input.Header("device_id")) 136 | token := c.Ctx.Input.Header("token") 137 | //id := c.Ctx.Input.Header("id") 138 | et := utils.EasyToken{} 139 | //token := strings.TrimSpace(c.Ctx.Request.Header.Get("Authorization")) 140 | validation, err := et.ValidateToken(token) 141 | if !validation { 142 | c.Ctx.ResponseWriter.WriteHeader(401) 143 | c.Data["json"] = Response{401, 401, fmt.Sprintf("%s", err), ""} 144 | c.ServeJSON() 145 | return 146 | } 147 | 148 | found, _ := models.GetUserByToken(token) 149 | if !found { 150 | c.Ctx.Output.SetStatus(201) 151 | c.Data["json"] = &Response{401, 401, "未找到相关的用户", ""} 152 | c.ServeJSON() 153 | return 154 | } 155 | 156 | // fields: col1,col2,entity.col3 157 | if v := c.GetString("fields"); v != "" { 158 | fields = strings.Split(v, ",") 159 | } 160 | // limit: 10 (default is 10) 161 | if v, err := c.GetInt("limit"); err == nil { 162 | limit = v 163 | } 164 | // offset: 0 (default is 0) 165 | if v, err := c.GetInt("offset"); err == nil { 166 | offset = v 167 | } 168 | // sortby: col1,col2 169 | if v := c.GetString("sortby"); v != "" { 170 | sortby = strings.Split(v, ",") 171 | } 172 | // order: desc,asc 173 | if v := c.GetString("order"); v != "" { 174 | order = strings.Split(v, ",") 175 | } 176 | // query: k:v,k:v 177 | if v := c.GetString("query"); v != "" { 178 | for _, cond := range strings.Split(v, ",") { 179 | kv := strings.SplitN(cond, ":", 2) 180 | if len(kv) != 2 { 181 | c.Data["json"] = errors.New("Error: invalid query key/value pair") 182 | c.ServeJSON() 183 | return 184 | } 185 | k, v := kv[0], kv[1] 186 | query[k] = v 187 | } 188 | } 189 | 190 | l, totalCount, err := models.GetAllAirAds(query, fields, sortby, order, offset, limit, deviceId) 191 | if err != nil { 192 | c.Data["json"] = err.Error() 193 | } else { 194 | var returnData = &GetAirAdData{totalCount, l} 195 | c.Data["json"] = &Response{0, 0, "ok", returnData} 196 | } 197 | c.ServeJSON() 198 | } 199 | 200 | // Put ... 201 | // @Title Put 202 | // @Description update the AirAd 203 | // @Param id path string true "The id you want to update" 204 | // @Param body body models.AirAd true "body for AirAd content" 205 | // @Success 200 {object} models.AirAd 206 | // @Failure 403 :id is not int 207 | // @router /:id [put] 208 | func (c *AirAdController) Put() { 209 | idStr := c.Ctx.Input.Param(":id") 210 | id, _ := strconv.Atoi(idStr) 211 | v := models.AirAd{Id: id} 212 | if err := json.Unmarshal(c.Ctx.Input.RequestBody, &v); err == nil { 213 | if err := models.UpdateAirAdById(&v); err == nil { 214 | c.Data["json"] = "OK" 215 | } else { 216 | c.Data["json"] = err.Error() 217 | } 218 | } else { 219 | c.Data["json"] = err.Error() 220 | } 221 | c.ServeJSON() 222 | } 223 | 224 | // Delete ... 225 | // @Title Delete 226 | // @Description delete the AirAd 227 | // @Param id path string true "The id you want to delete" 228 | // @Success 200 {string} delete success! 229 | // @Failure 403 id is empty 230 | // @router /:id [delete] 231 | func (c *AirAdController) Delete() { 232 | idStr := c.Ctx.Input.Param(":id") 233 | id, _ := strconv.Atoi(idStr) 234 | if err := models.DeleteAirAd(id); err == nil { 235 | c.Data["json"] = "OK" 236 | } else { 237 | c.Data["json"] = err.Error() 238 | } 239 | c.ServeJSON() 240 | } 241 | -------------------------------------------------------------------------------- /controllers/base.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | ) 6 | 7 | type BaseController struct { 8 | beego.Controller 9 | } 10 | 11 | // Controller Response is controller error info struct. 12 | type Response struct { 13 | Status int `json:"status"` 14 | ErrorCode int `json:"error_code"` 15 | ErrorMessage string `json:"error_message"` 16 | Data interface{} `json:"data"` 17 | } -------------------------------------------------------------------------------- /controllers/common.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | //"errors" 5 | //"regexp" 6 | //"strings" 7 | 8 | "github.com/astaxie/beego" 9 | //"github.com/astaxie/beego/validation" 10 | //"github.com/dgrijalva/jwt-go" 11 | ) 12 | 13 | // Predefined const error strings. 14 | const ( 15 | ErrInputData = "数据输入错误" 16 | ErrDatabase = "数据库操作错误" 17 | ErrDupUser = "用户信息已存在" 18 | ErrNoUser = "用户信息不存在" 19 | ErrPass = "密码不正确" 20 | ErrNoUserPass = "用户信息不存在或密码不正确" 21 | ErrNoUserChange = "用户信息不存在或数据未改变" 22 | ErrInvalidUser = "用户信息不正确" 23 | ErrOpenFile = "打开文件出错" 24 | ErrWriteFile = "写文件出错" 25 | ErrSystem = "操作系统错误" 26 | ) 27 | 28 | // UserData definition. 29 | type UserSuccessLoginData struct { 30 | AccessToken string `json:"access_token"` 31 | UserName string `json:"user_name"` 32 | } 33 | 34 | // CreateDevice definition. 35 | type CreateObjectData struct { 36 | Id int `json:"id"` 37 | } 38 | 39 | // GetDevices definition. 40 | type GetDeviceData struct { 41 | TotalCount int64 `json:"total_count"` 42 | Devices interface{} `json:"devices"` 43 | } 44 | 45 | // GetAirAds definition. 46 | type GetAirAdData struct { 47 | TotalCount int64 `json:"total_count"` 48 | AirAds interface{} `json:"airads"` 49 | } 50 | 51 | // Predefined controller error/success values. 52 | var ( 53 | successReturn = &Response{200, 0, "ok", "ok"} 54 | err404 = &Response{404, 404, "找不到网页", "找不到网页"} 55 | errInputData = &Response{400, 10001, "数据输入错误", "客户端参数错误"} 56 | errDatabase = &Response{500, 10002, "服务器错误", "数据库操作错误"} 57 | errUserToken = &Response{500, 10002, "服务器错误", "令牌操作错误"} 58 | errDupUser = &Response{400, 10003, "用户信息已存在", "数据库记录重复"} 59 | errNoUser = &Response{400, 10004, "用户信息不存在", "数据库记录不存在"} 60 | errPass = &Response{400, 10005, "用户信息不存在或密码不正确", "密码不正确"} 61 | errNoUserOrPass = &Response{400, 10006, "用户不存在或密码不正确", "数据库记录不存在或密码不正确"} 62 | errNoUserChange = &Response{400, 10007, "用户不存在或数据未改变", "数据库记录不存在或数据未改变"} 63 | errInvalidUser = &Response{400, 10008, "用户信息不正确", "Session信息不正确"} 64 | errOpenFile = &Response{500, 10009, "服务器错误", "打开文件出错"} 65 | errWriteFile = &Response{500, 10010, "服务器错误", "写文件出错"} 66 | errSystem = &Response{500, 10011, "服务器错误", "操作系统错误"} 67 | errExpired = &Response{400, 10012, "登录已过期", "验证token过期"} 68 | errPermission = &Response{400, 10013, "没有权限", "没有操作权限"} 69 | ) 70 | 71 | // BaseController definition. 72 | //type BaseController struct { 73 | // beego.Controller 74 | //} 75 | 76 | // RetError return error information in JSON. 77 | func (base *BaseController) RetError(e *Response) { 78 | if mode := beego.AppConfig.String("runmode"); mode == "prod" { 79 | e.Data = "" 80 | } 81 | 82 | base.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8") 83 | base.Ctx.ResponseWriter.WriteHeader(e.Status) 84 | base.Data["json"] = e 85 | base.ServeJSON() 86 | base.StopRun() 87 | } 88 | 89 | var sqlOp = map[string]string{ 90 | "eq": "=", 91 | "ne": "<>", 92 | "gt": ">", 93 | "ge": ">=", 94 | "lt": "<", 95 | "le": "<=", 96 | } 97 | 98 | // ParseQueryParm parse query parameters. 99 | // query=col1:op1:val1,col2:op2:val2,... 100 | // op: one of eq, ne, gt, ge, lt, le 101 | //func (base *BaseController) ParseQueryParameter() (v map[string]string, o map[string]string, err error) { 102 | // var nameRule = regexp.MustCompile("^[a-zA-Z0-9_]+$") 103 | // queryVal := make(map[string]string) 104 | // queryOp := make(map[string]string) 105 | // 106 | // query := base.GetString("query") 107 | // if query == "" { 108 | // return queryVal, queryOp, nil 109 | // } 110 | // 111 | // for _, cond := range strings.Split(query, ",") { 112 | // kov := strings.Split(cond, ":") 113 | // if len(kov) != 3 { 114 | // return queryVal, queryOp, errors.New("Query format != k:o:v") 115 | // } 116 | // 117 | // var key string 118 | // var value string 119 | // var operator string 120 | // if !nameRule.MatchString(kov[0]) { 121 | // return queryVal, queryOp, errors.New("Query key format is wrong") 122 | // } 123 | // key = kov[0] 124 | // if op, ok := sqlOp[kov[1]]; ok { 125 | // operator = op 126 | // } else { 127 | // return queryVal, queryOp, errors.New("Query operator is wrong") 128 | // } 129 | // value = strings.Replace(kov[2], "'", "\\'", -1) 130 | // 131 | // queryVal[key] = value 132 | // queryOp[key] = operator 133 | // } 134 | // 135 | // return queryVal, queryOp, nil 136 | //} 137 | 138 | // ParseOrderParameter parse order parameters. 139 | // order=col1:asc|desc,col2:asc|esc,... 140 | //func (base *BaseController) ParseOrderParameter() (o map[string]string, err error) { 141 | // var nameRule = regexp.MustCompile("^[a-zA-Z0-9_]+$") 142 | // order := make(map[string]string) 143 | // 144 | // v := base.GetString("order") 145 | // if v == "" { 146 | // return order, nil 147 | // } 148 | // 149 | // for _, cond := range strings.Split(v, ",") { 150 | // kv := strings.Split(cond, ":") 151 | // if len(kv) != 2 { 152 | // return order, errors.New("Order format != k:v") 153 | // } 154 | // if !nameRule.MatchString(kv[0]) { 155 | // return order, errors.New("Order key format is wrong") 156 | // } 157 | // if kv[1] != "asc" && kv[1] != "desc" { 158 | // return order, errors.New("Order val isn't asc/desc") 159 | // } 160 | // 161 | // order[kv[0]] = kv[1] 162 | // } 163 | // 164 | // return order, nil 165 | //} 166 | 167 | // ParseLimitParameter parse limit parameter. 168 | // limit=n 169 | //func (base *BaseController) ParseLimitParameter() (l int64, err error) { 170 | // if v, err := base.GetInt64("limit"); err != nil { 171 | // return 10, err 172 | // } else if v > 0 { 173 | // return v, nil 174 | // } else { 175 | // return 10, nil 176 | // } 177 | //} 178 | 179 | // ParseOffsetParameter parse offset parameter. 180 | // offset=n 181 | //func (base *BaseController) ParseOffsetParameter() (o int64, err error) { 182 | // if v, err := base.GetInt64("offset"); err != nil { 183 | // return 0, err 184 | // } else if v > 0 { 185 | // return v, nil 186 | // } else { 187 | // return 0, nil 188 | // } 189 | //} 190 | 191 | // VerifyForm use validation to verify input parameters. 192 | //func (base *BaseController) VerifyForm(obj interface{}) (err error) { 193 | // valid := validation.Validation{} 194 | // ok, err := valid.Valid(obj) 195 | // if err != nil { 196 | // return err 197 | // } 198 | // if !ok { 199 | // str := "" 200 | // for _, err := range valid.Errors { 201 | // str += err.Key + ":" + err.Message + ";" 202 | // } 203 | // return errors.New(str) 204 | // } 205 | // 206 | // return nil 207 | //} 208 | 209 | // ParseToken parse JWT token in http header. 210 | //func (base *BaseController) ParseToken() (t *jwt.Token, e *ControllerError) { 211 | // authString := base.Ctx.Input.Header("Authorization") 212 | // beego.Debug("AuthString:", authString) 213 | // 214 | // kv := strings.Split(authString, " ") 215 | // if len(kv) != 2 || kv[0] != "Bearer" { 216 | // beego.Error("AuthString invalid:", authString) 217 | // return nil, errInputData 218 | // } 219 | // tokenString := kv[1] 220 | // 221 | // // Parse token 222 | // token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { 223 | // return []byte("secret"), nil 224 | // }) 225 | // if err != nil { 226 | // beego.Error("Parse token:", err) 227 | // if ve, ok := err.(*jwt.ValidationError); ok { 228 | // if ve.Errors&jwt.ValidationErrorMalformed != 0 { 229 | // // That's not even a token 230 | // return nil, errInputData 231 | // } else if ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0 { 232 | // // Token is either expired or not active yet 233 | // return nil, errExpired 234 | // } else { 235 | // // Couldn't handle this token 236 | // return nil, errInputData 237 | // } 238 | // } else { 239 | // // Couldn't handle this token 240 | // return nil, errInputData 241 | // } 242 | // } 243 | // if !token.Valid { 244 | // beego.Error("Token invalid:", tokenString) 245 | // return nil, errInputData 246 | // } 247 | // beego.Debug("Token:", token) 248 | // 249 | // return token, nil 250 | //} 251 | -------------------------------------------------------------------------------- /controllers/default.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | ) 6 | 7 | // MainController definition. 8 | type MainController struct { 9 | beego.Controller 10 | } 11 | 12 | // Get method. 13 | func (c *MainController) Get() { 14 | c.Data["Website"] = "www.liudp.cn" 15 | c.Data["Email"] = "rubinliu@hotmail.com" 16 | c.TplName = "index.tpl" 17 | c.Render() 18 | } 19 | -------------------------------------------------------------------------------- /controllers/device.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "strconv" 7 | "strings" 8 | "github.com/rubinliudongpo/airad/models" 9 | "github.com/astaxie/beego" 10 | "github.com/rubinliudongpo/airad/utils" 11 | "fmt" 12 | ) 13 | 14 | // DeviceController operations for Device 15 | type DeviceController struct { 16 | beego.Controller 17 | } 18 | 19 | // URLMapping ... 20 | func (c *DeviceController) URLMapping() { 21 | c.Mapping("Post", c.Post) 22 | c.Mapping("GetOne", c.GetOne) 23 | c.Mapping("GetAll", c.GetAll) 24 | c.Mapping("Put", c.Put) 25 | c.Mapping("Delete", c.Delete) 26 | } 27 | 28 | // Post ... 29 | // @Title Post 30 | // @Description create Device 31 | // @Param body body models.Device true "body for Device content" 32 | // @Success 201 {int} models.Device 33 | // @Failure 403 body is empty 34 | // @router / [post] 35 | func (c *DeviceController) Post() { 36 | var v models.Device 37 | token := c.Ctx.Input.Header("token") 38 | //id := c.Ctx.Input.Header("id") 39 | et := utils.EasyToken{} 40 | //token := strings.TrimSpace(c.Ctx.Request.Header.Get("Authorization")) 41 | validation, err := et.ValidateToken(token) 42 | if !validation { 43 | c.Ctx.ResponseWriter.WriteHeader(401) 44 | c.Data["json"] = Response{401, 401, fmt.Sprintf("%s", err), ""} 45 | c.ServeJSON() 46 | return 47 | } 48 | 49 | if err := json.Unmarshal(c.Ctx.Input.RequestBody, &v); err == nil { 50 | if errorMessage := utils.CheckNewDevicePost(v.UserId, v.DeviceName, 51 | v.Address, v.Status, v.Latitude, v.Longitude); errorMessage != "ok"{ 52 | c.Ctx.ResponseWriter.WriteHeader(403) 53 | c.Data["json"] = Response{403, 403,errorMessage, ""} 54 | c.ServeJSON() 55 | return 56 | } 57 | if models.CheckDeviceName(v.DeviceName){ 58 | c.Ctx.ResponseWriter.WriteHeader(403) 59 | c.Data["json"] = Response{403, 403,"设备名已经注册了", ""} 60 | c.ServeJSON() 61 | return 62 | } 63 | 64 | if !models.CheckUserId(v.UserId){ 65 | c.Ctx.ResponseWriter.WriteHeader(403) 66 | c.Data["json"] = Response{403, 403,"用户ID不存在", ""} 67 | c.ServeJSON() 68 | return 69 | } 70 | 71 | if !models.CheckUserIdAndToken(v.UserId, token){ 72 | c.Ctx.ResponseWriter.WriteHeader(403) 73 | c.Data["json"] = Response{403, 403,"用户ID和Token不匹配", ""} 74 | c.ServeJSON() 75 | return 76 | } 77 | 78 | if deviceId, err := models.AddDevice(&v); err == nil { 79 | if user, err := models.GetUserById(v.UserId); err == nil { 80 | models.UpdateUserDeviceCount(user) 81 | c.Ctx.Output.SetStatus(201) 82 | var returnData = &CreateObjectData{int(deviceId)} 83 | c.Data["json"] = &Response{0, 0, "ok", returnData} 84 | } else { 85 | c.Ctx.ResponseWriter.WriteHeader(403) 86 | c.Data["json"] = Response{403, 403,"用户Id不存在", ""} 87 | c.ServeJSON() 88 | return 89 | } 90 | 91 | c.Ctx.Output.SetStatus(201) 92 | var returnData = &CreateObjectData{int(deviceId)} 93 | c.Data["json"] = &Response{0, 0, "ok", returnData} 94 | } else { 95 | c.Data["json"] = err.Error() 96 | } 97 | } else { 98 | c.Data["json"] = &Response{1, 1, "设备名注册失败", err.Error()} 99 | } 100 | c.ServeJSON() 101 | } 102 | 103 | // GetOne ... 104 | // @Title Get One 105 | // @Description get Device by id 106 | // @Param id path string true "The key for staticblock" 107 | // @Success 200 {object} models.Device 108 | // @Failure 403 :id is empty 109 | // @router /:id [get] 110 | func (c *DeviceController) GetOne() { 111 | idStr := c.Ctx.Input.Param(":id") 112 | id, _ := strconv.Atoi(idStr) 113 | v, err := models.GetDeviceById(id) 114 | if err != nil { 115 | c.Data["json"] = err.Error() 116 | } else { 117 | c.Data["json"] = v 118 | } 119 | c.ServeJSON() 120 | } 121 | 122 | // GetAll ... 123 | // @Title Get All 124 | // @Description get Device 125 | // @Param query query string false "Filter. e.g. col1:v1,col2:v2 ..." 126 | // @Param fields query string false "Fields returned. e.g. col1,col2 ..." 127 | // @Param sortby query string false "Sorted-by fields. e.g. col1,col2 ..." 128 | // @Param order query string false "Order corresponding to each sortby field, if single value, apply to all sortby fields. e.g. desc,asc ..." 129 | // @Param limit query string false "Limit the size of result set. Must be an integer" 130 | // @Param offset query string false "Start position of result set. Must be an integer" 131 | // @Success 200 {object} models.Device 132 | // @Failure 403 133 | // @router / [get] 134 | func (c *DeviceController) GetAll() { 135 | var fields []string 136 | var sortby []string 137 | var order []string 138 | var query = make(map[string]string) 139 | var limit int = 10 140 | var offset int 141 | var userId int 142 | 143 | token := c.Ctx.Input.Header("token") 144 | //id := c.Ctx.Input.Header("id") 145 | et := utils.EasyToken{} 146 | //token := strings.TrimSpace(c.Ctx.Request.Header.Get("Authorization")) 147 | valido, err := et.ValidateToken(token) 148 | if !valido { 149 | c.Ctx.ResponseWriter.WriteHeader(401) 150 | c.Data["json"] = Response{401, 401, fmt.Sprintf("%s", err), ""} 151 | c.ServeJSON() 152 | return 153 | } 154 | 155 | if found, user := models.GetUserByToken(token); !found { 156 | c.Ctx.Output.SetStatus(201) 157 | c.Data["json"] = &Response{401, 401, "未找到相关的用户", ""} 158 | c.ServeJSON() 159 | return 160 | } else { 161 | userId = user.Id 162 | } 163 | 164 | // fields: col1,col2,entity.col3 165 | if v := c.GetString("fields"); v != "" { 166 | fields = strings.Split(v, ",") 167 | } 168 | // limit: 10 (default is 10) 169 | if v, err := c.GetInt("limit"); err == nil { 170 | limit = v 171 | } 172 | // offset: 0 (default is 0) 173 | if v, err := c.GetInt("offset"); err == nil { 174 | offset = v 175 | } 176 | // sortby: col1,col2 177 | if v := c.GetString("sortby"); v != "" { 178 | sortby = strings.Split(v, ",") 179 | } 180 | // order: desc,asc 181 | if v := c.GetString("order"); v != "" { 182 | order = strings.Split(v, ",") 183 | } 184 | // query: k:v,k:v 185 | if v := c.GetString("query"); v != "" { 186 | for _, cond := range strings.Split(v, ",") { 187 | kv := strings.SplitN(cond, ":", 2) 188 | if len(kv) != 2 { 189 | c.Data["json"] = errors.New("Error: invalid query key/value pair") 190 | c.ServeJSON() 191 | return 192 | } 193 | k, v := kv[0], kv[1] 194 | query[k] = v 195 | } 196 | } 197 | 198 | l, totalCount, err := models.GetAllDevices(query, fields, sortby, order, offset, limit, userId) 199 | if err != nil { 200 | c.Data["json"] = err.Error() 201 | } else { 202 | var returnData = &GetDeviceData{totalCount, l} 203 | c.Data["json"] = &Response{0, 0, "ok", returnData} 204 | } 205 | c.ServeJSON() 206 | } 207 | 208 | // Put ... 209 | // @Title Put 210 | // @Description update the Device 211 | // @Param id path string true "The id you want to update" 212 | // @Param body body models.Device true "body for Device content" 213 | // @Success 200 {object} models.Device 214 | // @Failure 403 :id is not int 215 | // @router /:id [put] 216 | func (c *DeviceController) Put() { 217 | idStr := c.Ctx.Input.Param(":id") 218 | id, _ := strconv.Atoi(idStr) 219 | v := models.Device{Id: id} 220 | json.Unmarshal(c.Ctx.Input.RequestBody, &v) 221 | if err := models.UpdateDeviceById(&v); err == nil { 222 | c.Data["json"] = "OK" 223 | } else { 224 | c.Data["json"] = err.Error() 225 | } 226 | c.ServeJSON() 227 | } 228 | 229 | // Delete ... 230 | // @Title Delete 231 | // @Description delete the Device 232 | // @Param id path string true "The id you want to delete" 233 | // @Success 200 {string} delete success! 234 | // @Failure 403 id is empty 235 | // @router /:id [delete] 236 | func (c *DeviceController) Delete() { 237 | idStr := c.Ctx.Input.Param(":id") 238 | id, _ := strconv.Atoi(idStr) 239 | if err := models.DeleteDevice(id); err == nil { 240 | c.Data["json"] = "OK" 241 | } else { 242 | c.Data["json"] = err.Error() 243 | } 244 | c.ServeJSON() 245 | } 246 | 247 | // Delete ... 248 | // @Title Delete 249 | // @Description Get All Devices by User Id 250 | // @Param userId path int true 251 | // @Param limit path int true 252 | // @Param offset path int true 253 | // @Param fields path String true 254 | // @Param token path String true 255 | // @Success 200 {string} delete success! 256 | // @Failure 403 id is empty 257 | // @router /:id [post] 258 | func (c *DeviceController) GetDevicesByUserId() { 259 | var limit int = 10 260 | var offset int 261 | var fields []string 262 | var v models.DeviceRequestStruct 263 | 264 | if err := json.Unmarshal(c.Ctx.Input.RequestBody, &v); err == nil { 265 | if errorMessage := utils.CheckUserDevicePost(v.UserId, v.Limit, v.Offset); errorMessage != "ok"{ 266 | c.Ctx.ResponseWriter.WriteHeader(403) 267 | c.Data["json"] = Response{403, 403,errorMessage, ""} 268 | c.ServeJSON() 269 | return 270 | } 271 | if v := v.Fields; v != "" { 272 | fields = strings.Split(v, ",") 273 | } else { 274 | fields = strings.Split("DeviceName,Address,Status,Latitude,Longitude", ",") 275 | } 276 | // limit: 10 (default is 10) 277 | if para := v.Limit; para != 0 { 278 | limit = para 279 | } 280 | // offset: 0 (default is 0) 281 | if para := v.Offset; para != 0 { 282 | offset = para 283 | } 284 | if !models.CheckUserId(v.UserId){ 285 | c.Ctx.ResponseWriter.WriteHeader(403) 286 | c.Data["json"] = Response{403, 403,"用户ID不存在", ""} 287 | c.ServeJSON() 288 | return 289 | } 290 | if devices, err := models.GetDevicesByUserId(v.UserId, fields,limit, offset); err == nil { 291 | c.Data["json"] = devices 292 | } else { 293 | c.Data["json"] = err.Error() 294 | } 295 | } else { 296 | c.Data["json"] = &Response{1, 1, "设备结构解析失败", err.Error()} 297 | } 298 | c.ServeJSON() 299 | } -------------------------------------------------------------------------------- /controllers/error.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import "github.com/astaxie/beego" 4 | 5 | // ErrorController definition. 6 | type ErrorController struct { 7 | beego.Controller 8 | } 9 | 10 | 11 | func (c *ErrorController) Error404() { 12 | c.Data["json"] = Response{ 13 | ErrorCode: 404, 14 | ErrorMessage: "Not Found", 15 | } 16 | c.ServeJSON() 17 | } 18 | func (c *ErrorController) Error401() { 19 | c.Data["json"] = Response{ 20 | ErrorCode: 401, 21 | ErrorMessage: "Permission denied", 22 | } 23 | c.ServeJSON() 24 | } 25 | func (c *ErrorController) Error403() { 26 | c.Data["json"] = Response{ 27 | ErrorCode: 403, 28 | ErrorMessage: "Forbidden", 29 | } 30 | c.ServeJSON() 31 | } -------------------------------------------------------------------------------- /controllers/mqtt.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "strconv" 7 | "strings" 8 | "github.com/rubinliudongpo/airad/models" 9 | 10 | "github.com/astaxie/beego" 11 | ) 12 | 13 | // MqttController operations for Mqtt 14 | type MqttController struct { 15 | beego.Controller 16 | } 17 | 18 | // URLMapping ... 19 | func (c *MqttController) URLMapping() { 20 | c.Mapping("Post", c.Post) 21 | c.Mapping("GetOne", c.GetOne) 22 | c.Mapping("GetAll", c.GetAll) 23 | c.Mapping("Put", c.Put) 24 | c.Mapping("Delete", c.Delete) 25 | } 26 | 27 | // Post ... 28 | // @Title Post 29 | // @Description create Mqtt 30 | // @Param body body models.Mqtt true "body for Mqtt content" 31 | // @Success 201 {int} models.Mqtt 32 | // @Failure 403 body is empty 33 | // @router / [post] 34 | func (c *MqttController) Post() { 35 | var v models.Mqtt 36 | json.Unmarshal(c.Ctx.Input.RequestBody, &v) 37 | if _, err := models.AddMqtt(&v); err == nil { 38 | c.Ctx.Output.SetStatus(201) 39 | c.Data["json"] = v 40 | } else { 41 | c.Data["json"] = err.Error() 42 | } 43 | c.ServeJSON() 44 | } 45 | 46 | // GetOne ... 47 | // @Title Get One 48 | // @Description get Mqtt by id 49 | // @Param id path string true "The key for staticblock" 50 | // @Success 200 {object} models.Mqtt 51 | // @Failure 403 :id is empty 52 | // @router /:id [get] 53 | func (c *MqttController) GetOne() { 54 | idStr := c.Ctx.Input.Param(":id") 55 | id, _ := strconv.Atoi(idStr) 56 | v, err := models.GetMqttById(id) 57 | if err != nil { 58 | c.Data["json"] = err.Error() 59 | } else { 60 | c.Data["json"] = v 61 | } 62 | c.ServeJSON() 63 | } 64 | 65 | // GetAll ... 66 | // @Title Get All 67 | // @Description get Mqtt 68 | // @Param query query string false "Filter. e.g. col1:v1,col2:v2 ..." 69 | // @Param fields query string false "Fields returned. e.g. col1,col2 ..." 70 | // @Param sortby query string false "Sorted-by fields. e.g. col1,col2 ..." 71 | // @Param order query string false "Order corresponding to each sortby field, if single value, apply to all sortby fields. e.g. desc,asc ..." 72 | // @Param limit query string false "Limit the size of result set. Must be an integer" 73 | // @Param offset query string false "Start position of result set. Must be an integer" 74 | // @Success 200 {object} models.Mqtt 75 | // @Failure 403 76 | // @router / [get] 77 | func (c *MqttController) GetAll() { 78 | var fields []string 79 | var sortby []string 80 | var order []string 81 | var query = make(map[string]string) 82 | var limit int64 = 10 83 | var offset int64 84 | 85 | // fields: col1,col2,entity.col3 86 | if v := c.GetString("fields"); v != "" { 87 | fields = strings.Split(v, ",") 88 | } 89 | // limit: 10 (default is 10) 90 | if v, err := c.GetInt64("limit"); err == nil { 91 | limit = v 92 | } 93 | // offset: 0 (default is 0) 94 | if v, err := c.GetInt64("offset"); err == nil { 95 | offset = v 96 | } 97 | // sortby: col1,col2 98 | if v := c.GetString("sortby"); v != "" { 99 | sortby = strings.Split(v, ",") 100 | } 101 | // order: desc,asc 102 | if v := c.GetString("order"); v != "" { 103 | order = strings.Split(v, ",") 104 | } 105 | // query: k:v,k:v 106 | if v := c.GetString("query"); v != "" { 107 | for _, cond := range strings.Split(v, ",") { 108 | kv := strings.SplitN(cond, ":", 2) 109 | if len(kv) != 2 { 110 | c.Data["json"] = errors.New("Error: invalid query key/value pair") 111 | c.ServeJSON() 112 | return 113 | } 114 | k, v := kv[0], kv[1] 115 | query[k] = v 116 | } 117 | } 118 | 119 | l, err := models.GetAllMqtt(query, fields, sortby, order, offset, limit) 120 | if err != nil { 121 | c.Data["json"] = err.Error() 122 | } else { 123 | c.Data["json"] = l 124 | } 125 | c.ServeJSON() 126 | } 127 | 128 | // Put ... 129 | // @Title Put 130 | // @Description update the Mqtt 131 | // @Param id path string true "The id you want to update" 132 | // @Param body body models.Mqtt true "body for Mqtt content" 133 | // @Success 200 {object} models.Mqtt 134 | // @Failure 403 :id is not int 135 | // @router /:id [put] 136 | func (c *MqttController) Put() { 137 | idStr := c.Ctx.Input.Param(":id") 138 | id, _ := strconv.Atoi(idStr) 139 | v := models.Mqtt{Id: id} 140 | json.Unmarshal(c.Ctx.Input.RequestBody, &v) 141 | if err := models.UpdateMqttById(&v); err == nil { 142 | c.Data["json"] = "OK" 143 | } else { 144 | c.Data["json"] = err.Error() 145 | } 146 | c.ServeJSON() 147 | } 148 | 149 | // Delete ... 150 | // @Title Delete 151 | // @Description delete the Mqtt 152 | // @Param id path string true "The id you want to delete" 153 | // @Success 200 {string} delete success! 154 | // @Failure 403 id is empty 155 | // @router /:id [delete] 156 | func (c *MqttController) Delete() { 157 | idStr := c.Ctx.Input.Param(":id") 158 | id, _ := strconv.Atoi(idStr) 159 | if err := models.DeleteMqtt(id); err == nil { 160 | c.Data["json"] = "OK" 161 | } else { 162 | c.Data["json"] = err.Error() 163 | } 164 | c.ServeJSON() 165 | } 166 | -------------------------------------------------------------------------------- /controllers/mqttoption.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "strconv" 7 | "strings" 8 | "github.com/rubinliudongpo/airad/models" 9 | 10 | "github.com/astaxie/beego" 11 | ) 12 | 13 | // MqttOptionController operations for MqttOption 14 | type MqttOptionController struct { 15 | beego.Controller 16 | } 17 | 18 | // URLMapping ... 19 | func (c *MqttOptionController) URLMapping() { 20 | c.Mapping("Post", c.Post) 21 | c.Mapping("GetOne", c.GetOne) 22 | c.Mapping("GetAll", c.GetAll) 23 | c.Mapping("Put", c.Put) 24 | c.Mapping("Delete", c.Delete) 25 | } 26 | 27 | // Post ... 28 | // @Title Post 29 | // @Description create MqttOption 30 | // @Param body body models.MqttOption true "body for MqttOption content" 31 | // @Success 201 {int} models.MqttOption 32 | // @Failure 403 body is empty 33 | // @router / [post] 34 | func (c *MqttOptionController) Post() { 35 | var v models.MqttOption 36 | json.Unmarshal(c.Ctx.Input.RequestBody, &v) 37 | if _, err := models.AddMqttOption(&v); err == nil { 38 | c.Ctx.Output.SetStatus(201) 39 | c.Data["json"] = v 40 | } else { 41 | c.Data["json"] = err.Error() 42 | } 43 | c.ServeJSON() 44 | } 45 | 46 | // GetOne ... 47 | // @Title Get One 48 | // @Description get MqttOption by id 49 | // @Param id path string true "The key for staticblock" 50 | // @Success 200 {object} models.MqttOption 51 | // @Failure 403 :id is empty 52 | // @router /:id [get] 53 | func (c *MqttOptionController) GetOne() { 54 | idStr := c.Ctx.Input.Param(":id") 55 | id, _ := strconv.Atoi(idStr) 56 | v, err := models.GetMqttOptionById(id) 57 | if err != nil { 58 | c.Data["json"] = err.Error() 59 | } else { 60 | c.Data["json"] = v 61 | } 62 | c.ServeJSON() 63 | } 64 | 65 | // GetAll ... 66 | // @Title Get All 67 | // @Description get MqttOption 68 | // @Param query query string false "Filter. e.g. col1:v1,col2:v2 ..." 69 | // @Param fields query string false "Fields returned. e.g. col1,col2 ..." 70 | // @Param sortby query string false "Sorted-by fields. e.g. col1,col2 ..." 71 | // @Param order query string false "Order corresponding to each sortby field, if single value, apply to all sortby fields. e.g. desc,asc ..." 72 | // @Param limit query string false "Limit the size of result set. Must be an integer" 73 | // @Param offset query string false "Start position of result set. Must be an integer" 74 | // @Success 200 {object} models.MqttOption 75 | // @Failure 403 76 | // @router / [get] 77 | func (c *MqttOptionController) GetAll() { 78 | var fields []string 79 | var sortby []string 80 | var order []string 81 | var query = make(map[string]string) 82 | var limit int64 = 10 83 | var offset int64 84 | 85 | // fields: col1,col2,entity.col3 86 | if v := c.GetString("fields"); v != "" { 87 | fields = strings.Split(v, ",") 88 | } 89 | // limit: 10 (default is 10) 90 | if v, err := c.GetInt64("limit"); err == nil { 91 | limit = v 92 | } 93 | // offset: 0 (default is 0) 94 | if v, err := c.GetInt64("offset"); err == nil { 95 | offset = v 96 | } 97 | // sortby: col1,col2 98 | if v := c.GetString("sortby"); v != "" { 99 | sortby = strings.Split(v, ",") 100 | } 101 | // order: desc,asc 102 | if v := c.GetString("order"); v != "" { 103 | order = strings.Split(v, ",") 104 | } 105 | // query: k:v,k:v 106 | if v := c.GetString("query"); v != "" { 107 | for _, cond := range strings.Split(v, ",") { 108 | kv := strings.SplitN(cond, ":", 2) 109 | if len(kv) != 2 { 110 | c.Data["json"] = errors.New("Error: invalid query key/value pair") 111 | c.ServeJSON() 112 | return 113 | } 114 | k, v := kv[0], kv[1] 115 | query[k] = v 116 | } 117 | } 118 | 119 | l, err := models.GetAllMqttOption(query, fields, sortby, order, offset, limit) 120 | if err != nil { 121 | c.Data["json"] = err.Error() 122 | } else { 123 | c.Data["json"] = l 124 | } 125 | c.ServeJSON() 126 | } 127 | 128 | // Put ... 129 | // @Title Put 130 | // @Description update the MqttOption 131 | // @Param id path string true "The id you want to update" 132 | // @Param body body models.MqttOption true "body for MqttOption content" 133 | // @Success 200 {object} models.MqttOption 134 | // @Failure 403 :id is not int 135 | // @router /:id [put] 136 | func (c *MqttOptionController) Put() { 137 | idStr := c.Ctx.Input.Param(":id") 138 | id, _ := strconv.Atoi(idStr) 139 | v := models.MqttOption{Id: id} 140 | json.Unmarshal(c.Ctx.Input.RequestBody, &v) 141 | if err := models.UpdateMqttOptionById(&v); err == nil { 142 | c.Data["json"] = "OK" 143 | } else { 144 | c.Data["json"] = err.Error() 145 | } 146 | c.ServeJSON() 147 | } 148 | 149 | // Delete ... 150 | // @Title Delete 151 | // @Description delete the MqttOption 152 | // @Param id path string true "The id you want to delete" 153 | // @Success 200 {string} delete success! 154 | // @Failure 403 id is empty 155 | // @router /:id [delete] 156 | func (c *MqttOptionController) Delete() { 157 | idStr := c.Ctx.Input.Param(":id") 158 | id, _ := strconv.Atoi(idStr) 159 | if err := models.DeleteMqttOption(id); err == nil { 160 | c.Data["json"] = "OK" 161 | } else { 162 | c.Data["json"] = err.Error() 163 | } 164 | c.ServeJSON() 165 | } 166 | -------------------------------------------------------------------------------- /controllers/object.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/rubinliudongpo/airad/models" 5 | "encoding/json" 6 | 7 | "github.com/astaxie/beego" 8 | ) 9 | 10 | // Operations about object 11 | type ObjectController struct { 12 | beego.Controller 13 | } 14 | 15 | // @Title Create 16 | // @Description create object 17 | // @Param body body models.Object true "The object content" 18 | // @Success 200 {string} models.Object.Id 19 | // @Failure 403 body is empty 20 | // @router / [post] 21 | func (o *ObjectController) Post() { 22 | var ob models.Object 23 | json.Unmarshal(o.Ctx.Input.RequestBody, &ob) 24 | objectid := models.AddOne(ob) 25 | o.Data["json"] = map[string]string{"ObjectId": objectid} 26 | o.ServeJSON() 27 | } 28 | 29 | // @Title Get 30 | // @Description find object by objectid 31 | // @Param objectId path string true "the objectid you want to get" 32 | // @Success 200 {object} models.Object 33 | // @Failure 403 :objectId is empty 34 | // @router /:objectId [get] 35 | func (o *ObjectController) Get() { 36 | objectId := o.Ctx.Input.Param(":objectId") 37 | if objectId != "" { 38 | ob, err := models.GetOne(objectId) 39 | if err != nil { 40 | o.Data["json"] = err.Error() 41 | } else { 42 | o.Data["json"] = ob 43 | } 44 | } 45 | o.ServeJSON() 46 | } 47 | 48 | // @Title GetAll 49 | // @Description get all objects 50 | // @Success 200 {object} models.Object 51 | // @Failure 403 :objectId is empty 52 | // @router / [get] 53 | func (o *ObjectController) GetAll() { 54 | obs := models.GetAll() 55 | o.Data["json"] = obs 56 | o.ServeJSON() 57 | } 58 | 59 | // @Title Update 60 | // @Description update the object 61 | // @Param objectId path string true "The objectid you want to update" 62 | // @Param body body models.Object true "The body" 63 | // @Success 200 {object} models.Object 64 | // @Failure 403 :objectId is empty 65 | // @router /:objectId [put] 66 | func (o *ObjectController) Put() { 67 | objectId := o.Ctx.Input.Param(":objectId") 68 | var ob models.Object 69 | json.Unmarshal(o.Ctx.Input.RequestBody, &ob) 70 | 71 | err := models.Update(objectId, ob.Score) 72 | if err != nil { 73 | o.Data["json"] = err.Error() 74 | } else { 75 | o.Data["json"] = "update success!" 76 | } 77 | o.ServeJSON() 78 | } 79 | 80 | // @Title Delete 81 | // @Description delete the object 82 | // @Param objectId path string true "The objectId you want to delete" 83 | // @Success 200 {string} delete success! 84 | // @Failure 403 objectId is empty 85 | // @router /:objectId [delete] 86 | func (o *ObjectController) Delete() { 87 | objectId := o.Ctx.Input.Param(":objectId") 88 | models.Delete(objectId) 89 | o.Data["json"] = "delete success!" 90 | o.ServeJSON() 91 | } 92 | 93 | -------------------------------------------------------------------------------- /controllers/user.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/rubinliudongpo/airad/models" 5 | "github.com/rubinliudongpo/airad/utils" 6 | "encoding/json" 7 | "errors" 8 | "github.com/astaxie/beego" 9 | "strings" 10 | "strconv" 11 | "time" 12 | "fmt" 13 | ) 14 | 15 | // Operations about Users 16 | type UserController struct { 17 | beego.Controller 18 | } 19 | 20 | // URLMapping ... 21 | func (c *UserController) URLMapping() { 22 | c.Mapping("Post", c.Post) 23 | c.Mapping("GetOne", c.GetOne) 24 | c.Mapping("GetAll", c.GetAll) 25 | c.Mapping("Put", c.Put) 26 | c.Mapping("Delete", c.Delete) 27 | } 28 | 29 | // @Title CreateUser 30 | // @Description create users 31 | // @Param body body models.User true "body for user content" 32 | // @Success 200 {int} models.User.Id 33 | // @Failure 403 body is empty 34 | // @router / [post] 35 | func (c *UserController) Post() { 36 | var v models.User 37 | if err := json.Unmarshal(c.Ctx.Input.RequestBody, &v); err == nil { 38 | if errorMessage := utils.CheckNewUserPost(v.Username, v.Password, 39 | v.Age, v.Gender, v.Address, v.Email); errorMessage != "ok"{ 40 | c.Ctx.ResponseWriter.WriteHeader(403) 41 | c.Data["json"] = Response{403, 403,errorMessage, ""} 42 | c.ServeJSON() 43 | return 44 | } 45 | if models.CheckUserName(v.Username){ 46 | c.Ctx.ResponseWriter.WriteHeader(403) 47 | c.Data["json"] = Response{403, 403,"用户名称已经注册了", ""} 48 | c.ServeJSON() 49 | return 50 | } 51 | if models.CheckEmail(v.Email) { 52 | c.Ctx.ResponseWriter.WriteHeader(403) 53 | c.Data["json"] = Response{403, 403,"邮箱已经注册了", ""} 54 | c.ServeJSON() 55 | return 56 | } 57 | 58 | if user, err := models.AddUser(&v); err == nil { 59 | c.Ctx.Output.SetStatus(201) 60 | var returnData = &UserSuccessLoginData{user.Token, user.Username} 61 | c.Data["json"] = &Response{0, 0, "ok", returnData} 62 | } else { 63 | c.Data["json"] = &Response{1, 1, "用户注册失败", err.Error()} 64 | } 65 | } else { 66 | c.Data["json"] = &Response{1, 1, "用户注册失败", err.Error()} 67 | } 68 | c.ServeJSON() 69 | } 70 | 71 | // @Title GetAll 72 | // @Description get all Users 73 | // @Success 200 {object} models.User 74 | // @router / [get] 75 | func (c *UserController) GetAll() { 76 | var fields []string 77 | var sortby []string 78 | var order []string 79 | var query = make(map[string]string) 80 | var limit int = 10 81 | var offset int 82 | 83 | token := c.Ctx.Input.Header("token") 84 | //id := c.Ctx.Input.Header("id") 85 | et := utils.EasyToken{} 86 | //token := strings.TrimSpace(c.Ctx.Request.Header.Get("Authorization")) 87 | validation, err := et.ValidateToken(token) 88 | if !validation { 89 | c.Ctx.ResponseWriter.WriteHeader(401) 90 | c.Data["json"] = Response{401, 401, fmt.Sprintf("%s", err), ""} 91 | c.ServeJSON() 92 | return 93 | } 94 | 95 | // fields: col1,col2,entity.col3 96 | if v := c.GetString("fields"); v != "" { 97 | fields = strings.Split(v, ",") 98 | } else { 99 | fields = strings.Split("Username,Gender,Age,Address,Email,Token", ",") 100 | } 101 | // limit: 10 (default is 10) 102 | if v, err := c.GetInt("limit"); err == nil { 103 | limit = v 104 | } 105 | // offset: 0 (default is 0) 106 | if v, err := c.GetInt("offset"); err == nil { 107 | offset = v 108 | } 109 | // sortby: col1,col2 110 | if v := c.GetString("sortby"); v != "" { 111 | sortby = strings.Split(v, ",") 112 | } 113 | // order: desc,asc 114 | if v := c.GetString("order"); v != "" { 115 | order = strings.Split(v, ",") 116 | } 117 | // query: k:v,k:v 118 | if v := c.GetString("query"); v != "" { 119 | for _, cond := range strings.Split(v, ",") { 120 | kv := strings.SplitN(cond, ":", 2) 121 | if len(kv) != 2 { 122 | c.Data["json"] = errors.New("Error: invalid query key/value pair") 123 | c.ServeJSON() 124 | return 125 | } 126 | k, v := kv[0], kv[1] 127 | query[k] = v 128 | } 129 | } 130 | 131 | l, err := models.GetAllUser(query, fields, sortby, order, offset, limit) 132 | if err != nil { 133 | c.Data["json"] = err.Error() 134 | } else { 135 | c.Data["json"] = l 136 | } 137 | c.ServeJSON() 138 | } 139 | 140 | // GetOne ... 141 | // @Title GetOne 142 | // @Description get User by id 143 | // @Param id path string true "The key for static block" 144 | // @Success 200 {object} models.AirAd 145 | // @Failure 403 :id is empty 146 | // @router /:id [get] 147 | func (c *UserController) GetOne() { 148 | token := c.Ctx.Input.Header("token") 149 | //idStr := c.Ctx.Input.Param("id") 150 | idStr := c.Ctx.Input.Param(":id") 151 | //token := c.Ctx.Input.Param(":token") 152 | et := utils.EasyToken{} 153 | //token := strings.TrimSpace(c.Ctx.Request.Header.Get("Authorization")) 154 | valido, err := et.ValidateToken(token) 155 | if !valido { 156 | c.Ctx.ResponseWriter.WriteHeader(401) 157 | c.Data["json"] = Response{401, 401, fmt.Sprintf("%s", err), ""} 158 | c.ServeJSON() 159 | return 160 | } 161 | 162 | id, _ := strconv.Atoi(idStr) 163 | v, err := models.GetUserById(id) 164 | if v == nil { 165 | c.Data["json"] = err.Error() 166 | } else { 167 | c.Data["json"] = v 168 | } 169 | c.ServeJSON() 170 | 171 | } 172 | 173 | // @Title Update 174 | // @Description update the user 175 | // @Param uid path string true "The uid you want to update" 176 | // @Param body body models.User true "body for user content" 177 | // @Success 200 {object} models.User 178 | // @Failure 403 :uid is not int 179 | // @router /:uid [put] 180 | func (c *UserController) Put() { 181 | idStr := c.Ctx.Input.Param(":id") 182 | id, _ := strconv.Atoi(idStr) 183 | v := models.User{Id: id} 184 | if err := json.Unmarshal(c.Ctx.Input.RequestBody, &v); err == nil { 185 | if err := models.UpdateUserById(&v); err == nil { 186 | c.Data["json"] = successReturn 187 | } else { 188 | c.Data["json"] = err.Error() 189 | } 190 | } else { 191 | c.Data["json"] = err.Error() 192 | } 193 | c.ServeJSON() 194 | } 195 | 196 | // @Title Delete 197 | // @Description delete the user 198 | // @Param uid path string true "The uid you want to delete" 199 | // @Success 200 {string} delete success! 200 | // @Failure 403 uid is empty 201 | // @router /:uid [delete] 202 | func (c *UserController) Delete() { 203 | idStr := c.Ctx.Input.Param(":id") 204 | id, _ := strconv.Atoi(idStr) 205 | if err := models.DeleteUser(id); err == nil { 206 | c.Data["json"] = successReturn 207 | } else { 208 | c.Data["json"] = err.Error() 209 | } 210 | c.ServeJSON() 211 | } 212 | 213 | // @Title Login 214 | // @Description Logs user into the system 215 | // @Param username query string true "The username for login" 216 | // @Param password query string true "The password for login" 217 | // @Success 200 {string} login success 218 | // @Failure 403 user not exist 219 | // @router /login [POST] 220 | func (c *UserController) Login() { 221 | var reqData struct { 222 | Username string `valid:"Required"` 223 | Password string `valid:"Required"` 224 | } 225 | var token string 226 | 227 | if err := json.Unmarshal(c.Ctx.Input.RequestBody, &reqData); err == nil { 228 | if errorMessage := utils.CheckUsernamePassword(reqData.Username, reqData.Password); errorMessage != "ok"{ 229 | c.Ctx.ResponseWriter.WriteHeader(403) 230 | c.Data["json"] = Response{403, 403,errorMessage, ""} 231 | c.ServeJSON() 232 | return 233 | } 234 | if ok, user := models.Login(reqData.Username, reqData.Password); ok { 235 | et := utils.EasyToken{} 236 | validation, err := et.ValidateToken(user.Token) 237 | if !validation { 238 | et = utils.EasyToken{ 239 | Username: user.Username, 240 | Uid: int64(user.Id), 241 | Expires: time.Now().Unix() + 2 * 3600, 242 | } 243 | token, err = et.GetToken() 244 | if token == "" || err != nil { 245 | c.Data["json"] = errUserToken 246 | c.ServeJSON() 247 | return 248 | } else { 249 | models.UpdateUserToken(user, token) 250 | } 251 | } else { 252 | token = user.Token 253 | } 254 | models.UpdateUserLastLogin(user) 255 | 256 | var returnData = &UserSuccessLoginData{token, user.Username} 257 | c.Data["json"] = &Response{0, 0, "ok", returnData} 258 | } else { 259 | c.Data["json"] = &errNoUserOrPass 260 | } 261 | } else { 262 | c.Data["json"] = &errNoUserOrPass 263 | } 264 | c.ServeJSON() 265 | } 266 | 267 | // @Title 认证测试 268 | // @Description 测试错误码 269 | // @Success 200 {object} 270 | // @Failure 401 unauthorized 271 | // @router /auth [get] 272 | func (c *UserController) Auth() { 273 | et := utils.EasyToken{} 274 | token := strings.TrimSpace(c.Ctx.Request.Header.Get("Authorization")) 275 | validation, err := et.ValidateToken(token) 276 | if !validation { 277 | c.Ctx.ResponseWriter.WriteHeader(401) 278 | c.Data["json"] = Response{401, 401, fmt.Sprintf("%s", err), ""} 279 | c.ServeJSON() 280 | return 281 | } 282 | 283 | c.Data["json"] = Response{0, 0, "is login", ""} 284 | c.ServeJSON() 285 | } 286 | 287 | // @Title logout 288 | // @Description Logs out current logged in user session 289 | // @Success 200 {string} logout success 290 | // @router /logout [get] 291 | func (u *UserController) Logout() { 292 | u.Data["json"] = successReturn 293 | u.ServeJSON() 294 | } 295 | 296 | -------------------------------------------------------------------------------- /database/airad.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 5.7.19, for osx10.12 (x86_64) 2 | -- 3 | -- Host: localhost Database: airad 4 | -- ------------------------------------------------------ 5 | -- Server version 5.7.19 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!40101 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `air_ad` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `air_ad`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!40101 SET character_set_client = utf8 */; 25 | CREATE TABLE `air_ad` ( 26 | `id` int(11) NOT NULL AUTO_INCREMENT, 27 | `device_id` int(11) NOT NULL DEFAULT '0', 28 | `created_at` bigint(20) NOT NULL DEFAULT '0', 29 | `nh3` varchar(4) NOT NULL DEFAULT '', 30 | `co` varchar(4) NOT NULL DEFAULT '', 31 | `o3` varchar(4) NOT NULL DEFAULT '', 32 | `pm25` varchar(4) NOT NULL DEFAULT '', 33 | `pm10` varchar(4) NOT NULL DEFAULT '', 34 | `so2` varchar(4) NOT NULL DEFAULT '', 35 | `temperature` varchar(4) NOT NULL DEFAULT '', 36 | `humidity` varchar(4) NOT NULL DEFAULT '', 37 | `aqi_quality` varchar(4) NOT NULL DEFAULT '', 38 | `suggest` varchar(4) NOT NULL DEFAULT '', 39 | PRIMARY KEY (`id`) 40 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 41 | /*!40101 SET character_set_client = @saved_cs_client */; 42 | 43 | -- 44 | -- Dumping data for table `air_ad` 45 | -- 46 | 47 | LOCK TABLES `air_ad` WRITE; 48 | /*!40000 ALTER TABLE `air_ad` DISABLE KEYS */; 49 | /*!40000 ALTER TABLE `air_ad` ENABLE KEYS */; 50 | UNLOCK TABLES; 51 | 52 | -- 53 | -- Table structure for table `device` 54 | -- 55 | 56 | DROP TABLE IF EXISTS `device`; 57 | /*!40101 SET @saved_cs_client = @@character_set_client */; 58 | /*!40101 SET character_set_client = utf8 */; 59 | CREATE TABLE `device` ( 60 | `id` int(11) NOT NULL AUTO_INCREMENT, 61 | `user_id` int(11) NOT NULL DEFAULT '0', 62 | `device_name` varchar(32) NOT NULL DEFAULT '', 63 | `address` varchar(50) NOT NULL DEFAULT '', 64 | `status` int(11) NOT NULL DEFAULT '0', 65 | `created_at` bigint(20) NOT NULL DEFAULT '0', 66 | `updated_at` bigint(20) NOT NULL DEFAULT '0', 67 | `latitude` varchar(12) NOT NULL DEFAULT '', 68 | `longitude` varchar(12) NOT NULL DEFAULT '', 69 | `airad_count` bigint(20) NOT NULL DEFAULT '0', 70 | PRIMARY KEY (`id`), 71 | UNIQUE KEY `device_name` (`device_name`) 72 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 73 | /*!40101 SET character_set_client = @saved_cs_client */; 74 | 75 | -- 76 | -- Dumping data for table `device` 77 | -- 78 | 79 | LOCK TABLES `device` WRITE; 80 | /*!40000 ALTER TABLE `device` DISABLE KEYS */; 81 | /*!40000 ALTER TABLE `device` ENABLE KEYS */; 82 | UNLOCK TABLES; 83 | 84 | -- 85 | -- Table structure for table `mqtt` 86 | -- 87 | 88 | DROP TABLE IF EXISTS `mqtt`; 89 | /*!40101 SET @saved_cs_client = @@character_set_client */; 90 | /*!40101 SET character_set_client = utf8 */; 91 | CREATE TABLE `mqtt` ( 92 | `id` int(11) NOT NULL AUTO_INCREMENT, 93 | `device_id` int(11) NOT NULL DEFAULT '0', 94 | `mqtt_option_id` int(11) NOT NULL DEFAULT '0', 95 | `qos` tinyint(3) unsigned NOT NULL DEFAULT '0', 96 | `retain` tinyint(1) NOT NULL DEFAULT '0', 97 | `topic_name` varchar(255) NOT NULL DEFAULT '', 98 | `topic_filter` varchar(255) NOT NULL DEFAULT '', 99 | PRIMARY KEY (`id`) 100 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 101 | /*!40101 SET character_set_client = @saved_cs_client */; 102 | 103 | -- 104 | -- Dumping data for table `mqtt` 105 | -- 106 | 107 | LOCK TABLES `mqtt` WRITE; 108 | /*!40000 ALTER TABLE `mqtt` DISABLE KEYS */; 109 | /*!40000 ALTER TABLE `mqtt` ENABLE KEYS */; 110 | UNLOCK TABLES; 111 | 112 | -- 113 | -- Table structure for table `mqtt_option` 114 | -- 115 | 116 | DROP TABLE IF EXISTS `mqtt_option`; 117 | /*!40101 SET @saved_cs_client = @@character_set_client */; 118 | /*!40101 SET character_set_client = utf8 */; 119 | CREATE TABLE `mqtt_option` ( 120 | `id` int(11) NOT NULL AUTO_INCREMENT, 121 | `client_id` varchar(255) NOT NULL DEFAULT '', 122 | `conn_ack_timeout` bigint(20) NOT NULL DEFAULT '0', 123 | `user_name` varchar(32) NOT NULL DEFAULT '', 124 | `password` varchar(128) NOT NULL DEFAULT '', 125 | `clean_session` tinyint(1) NOT NULL DEFAULT '0', 126 | `keep_alive` smallint(5) unsigned NOT NULL DEFAULT '0', 127 | `will_topic` varchar(255) NOT NULL DEFAULT '', 128 | `will_message` varchar(255) NOT NULL DEFAULT '', 129 | `will_qos` tinyint(1) NOT NULL DEFAULT '0', 130 | `will_retain` tinyint(1) NOT NULL DEFAULT '0', 131 | PRIMARY KEY (`id`) 132 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 133 | /*!40101 SET character_set_client = @saved_cs_client */; 134 | 135 | -- 136 | -- Dumping data for table `mqtt_option` 137 | -- 138 | 139 | LOCK TABLES `mqtt_option` WRITE; 140 | /*!40000 ALTER TABLE `mqtt_option` DISABLE KEYS */; 141 | /*!40000 ALTER TABLE `mqtt_option` ENABLE KEYS */; 142 | UNLOCK TABLES; 143 | 144 | -- 145 | -- Table structure for table `user` 146 | -- 147 | 148 | DROP TABLE IF EXISTS `user`; 149 | /*!40101 SET @saved_cs_client = @@character_set_client */; 150 | /*!40101 SET character_set_client = utf8 */; 151 | CREATE TABLE `user` ( 152 | `id` int(11) NOT NULL AUTO_INCREMENT, 153 | `username` varchar(32) NOT NULL DEFAULT '', 154 | `password` varchar(128) NOT NULL DEFAULT '', 155 | `salt` varchar(128) NOT NULL DEFAULT '', 156 | `token` varchar(256) NOT NULL DEFAULT '', 157 | `gender` int(11) NOT NULL DEFAULT '0', 158 | `age` int(11) NOT NULL DEFAULT '0', 159 | `address` varchar(50) NOT NULL DEFAULT '', 160 | `email` varchar(50) NOT NULL DEFAULT '', 161 | `last_login` bigint(20) NOT NULL DEFAULT '0', 162 | `status` int(11) NOT NULL DEFAULT '0', 163 | `created_at` bigint(20) NOT NULL DEFAULT '0', 164 | `updated_at` bigint(20) NOT NULL DEFAULT '0', 165 | `device_count` int(11) NOT NULL DEFAULT '0', 166 | PRIMARY KEY (`id`), 167 | UNIQUE KEY `username` (`username`) 168 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 169 | /*!40101 SET character_set_client = @saved_cs_client */; 170 | 171 | -- 172 | -- Dumping data for table `user` 173 | -- 174 | 175 | LOCK TABLES `user` WRITE; 176 | /*!40000 ALTER TABLE `user` DISABLE KEYS */; 177 | /*!40000 ALTER TABLE `user` ENABLE KEYS */; 178 | UNLOCK TABLES; 179 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 180 | 181 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 182 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 183 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 184 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 185 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 186 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 187 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 188 | 189 | -- Dump completed on 2018-04-16 11:49:30 190 | -------------------------------------------------------------------------------- /logs/logs.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubinliudongpo/airad/3968aa1f7cefb098976544aa463db6535204f15a/logs/logs.log -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | 4 | import ( 5 | _ "github.com/rubinliudongpo/airad/routers" 6 | "github.com/rubinliudongpo/airad/utils" 7 | 8 | 9 | "github.com/astaxie/beego" 10 | "github.com/rubinliudongpo/airad/controllers" 11 | ) 12 | 13 | func main() { 14 | utils.InitSql() 15 | utils.InitTemplate() 16 | utils.InitCache() 17 | utils.InitBootStrap() 18 | beego.ErrorController(&controllers.ErrorController{}) 19 | 20 | beego.Run() 21 | } -------------------------------------------------------------------------------- /models/airad.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "reflect" 7 | "strings" 8 | "github.com/astaxie/beego/orm" 9 | "time" 10 | ) 11 | 12 | type AirAd struct { 13 | Id int `json:"id, omitempty" orm:"column(id);pk;unique;auto_increment"` 14 | DeviceId int `json:"device_id" orm:"column(device_id);size(11)"` 15 | CreatedAt int64 `json:"created_at, omitempty" orm:"column(created_at);size(11)"` 16 | Nh3 string `json:"nh3, omitempty" orm:"column(nh3);size(4)"` 17 | Co string `json:"co, omitempty" orm:"column(co);size(4)"` 18 | O3 string `json:"o3, omitempty" orm:"column(o3);size(4)"` 19 | Pm25 string `json:"pm25, omitempty" orm:"column(pm25);size(4)"` 20 | Pm10 string `json:"pm10, omitempty" orm:"column(pm10);size(4)"` 21 | So2 string `json:"so2, omitempty" orm:"column(so2);size(4)"` 22 | Temperature string `json:"temperature, omitempty" orm:"column(temperature);size(4)"` 23 | Humidity string `json:"humidity, omitempty" orm:"column(humidity);size(4)"` 24 | AqiQuality string `json:"aqi_quality, omitempty" orm:"column(aqi_quality);size(4)"` 25 | Suggest string `json:"suggest, omitempty" orm:"column(suggest);size(4)"` 26 | //Device *Device `orm:"rel(fk)"` 27 | } 28 | 29 | func init() { 30 | orm.RegisterModel(new(AirAd)) 31 | } 32 | 33 | func AirAds() orm.QuerySeter { 34 | return orm.NewOrm().QueryTable(new(AirAd)) 35 | } 36 | 37 | // AddAirAd insert a new AirAd into database and returns 38 | // last inserted Id on success. 39 | func AddAirAd(m *AirAd) (id int64, err error) { 40 | o := orm.NewOrm() 41 | 42 | CreatedAt := time.Now().UTC().Unix() 43 | 44 | airAd := AirAd{ 45 | DeviceId:m.DeviceId, 46 | Nh3:m.Nh3, 47 | Pm10:m.Pm10, 48 | Pm25:m.Pm25, 49 | Co:m.Co, 50 | O3:m.O3, 51 | So2:m.So2, 52 | Temperature:m.Temperature, 53 | Humidity:m.Humidity, 54 | AqiQuality:m.AqiQuality, 55 | Suggest:m.Suggest, 56 | CreatedAt:CreatedAt, 57 | } 58 | 59 | id, err = o.Insert(&airAd) 60 | if err == nil{ 61 | return id, err 62 | } 63 | 64 | return 0, err 65 | } 66 | 67 | // GetAirAdById retrieves AirAd by Id. Returns error if 68 | // Id doesn't exist 69 | func GetAirAdById(id int) (v *AirAd, err error) { 70 | o := orm.NewOrm() 71 | v = &AirAd{Id: id} 72 | if err = o.QueryTable(new(AirAd)).Filter("Id", id).RelatedSel().One(v); err == nil { 73 | return v, nil 74 | } 75 | return nil, err 76 | } 77 | 78 | // 检测DeviceId是否存在 79 | func CheckDeviceId(deviceId int) bool { 80 | exist := Devices().Filter("Id", deviceId).Exist() 81 | return exist 82 | } 83 | 84 | // 检测DeviceId vs. Token 是否匹配 85 | func CheckDeviceIdAndToken(deviceId int, token string) bool { 86 | o := orm.NewOrm() 87 | var device Device 88 | if err := o.QueryTable(new(Device)).Filter("Id", deviceId).RelatedSel().One(&device); err == nil { 89 | exist := Users().Filter("Id", device.UserId).Filter("Token", token).Exist() 90 | return exist 91 | } 92 | return false 93 | } 94 | 95 | 96 | // GetAllAirAds retrieves all AirAd matches certain condition. Returns empty list if 97 | // no records exist 98 | func GetAllAirAds(query map[string]string, fields []string, sortby []string, order []string, 99 | offset int, limit int, deviceId int) (ml []interface{}, totalCount int64,err error) { 100 | o := orm.NewOrm() 101 | qs := o.QueryTable(new(AirAd)) 102 | // query k=v 103 | for k, v := range query { 104 | // rewrite dot-notation to Object__Attribute 105 | k = strings.Replace(k, ".", "__", -1) 106 | qs = qs.Filter(k, v) 107 | } 108 | // order by: 109 | var sortFields []string 110 | if len(sortby) != 0 { 111 | if len(sortby) == len(order) { 112 | // 1) for each sort field, there is an associated order 113 | for i, v := range sortby { 114 | orderby := "" 115 | if order[i] == "desc" { 116 | orderby = "-" + v 117 | } else if order[i] == "asc" { 118 | orderby = v 119 | } else { 120 | return nil, 0,errors.New("Error: Invalid order. Must be either [asc|desc]") 121 | } 122 | sortFields = append(sortFields, orderby) 123 | } 124 | qs = qs.OrderBy(sortFields...) 125 | } else if len(sortby) != len(order) && len(order) == 1 { 126 | // 2) there is exactly one order, all the sorted fields will be sorted by this order 127 | for _, v := range sortby { 128 | orderby := "" 129 | if order[0] == "desc" { 130 | orderby = "-" + v 131 | } else if order[0] == "asc" { 132 | orderby = v 133 | } else { 134 | return nil, 0, errors.New("Error: Invalid order. Must be either [asc|desc]") 135 | } 136 | sortFields = append(sortFields, orderby) 137 | } 138 | } else if len(sortby) != len(order) && len(order) != 1 { 139 | return nil, 0, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1") 140 | } 141 | } else { 142 | if len(order) != 0 { 143 | return nil, 0, errors.New("Error: unused 'order' fields") 144 | } 145 | } 146 | 147 | var l []AirAd 148 | qs = qs.OrderBy(sortFields...).RelatedSel() 149 | totalCount, err = qs.Filter("DeviceId", deviceId).Count() 150 | if _, err = qs.Filter("DeviceId", deviceId).Limit(limit, offset).All(&l, fields...); err == nil { 151 | if len(fields) == 0 { 152 | for _, v := range l { 153 | ml = append(ml, v) 154 | } 155 | } else { 156 | // trim unused fields 157 | for _, v := range l { 158 | m := make(map[string]interface{}) 159 | val := reflect.ValueOf(v) 160 | for _, fname := range fields { 161 | m[fname] = val.FieldByName(fname).Interface() 162 | } 163 | ml = append(ml, m) 164 | } 165 | } 166 | return ml, totalCount,nil 167 | } 168 | return nil, 0, err 169 | } 170 | 171 | // UpdateAirAd updates AirAd by Id and returns error if 172 | // the record to be updated doesn't exist 173 | func UpdateAirAdById(m *AirAd) (err error) { 174 | o := orm.NewOrm() 175 | v := AirAd{Id: m.Id} 176 | // ascertain id exists in the database 177 | if err = o.Read(&v); err == nil { 178 | var num int64 179 | if num, err = o.Update(m); err == nil { 180 | fmt.Println("Number of records updated in database:", num) 181 | } 182 | } 183 | return 184 | } 185 | 186 | // DeleteAirAd deletes AirAd by Id and returns error if 187 | // the record to be deleted doesn't exist 188 | func DeleteAirAd(id int) (err error) { 189 | o := orm.NewOrm() 190 | v := AirAd{Id: id} 191 | // ascertain id exists in the database 192 | if err = o.Read(&v); err == nil { 193 | var num int64 194 | if num, err = o.Delete(&AirAd{Id: id}); err == nil { 195 | fmt.Println("Number of records deleted in database:", num) 196 | } 197 | } 198 | return 199 | } -------------------------------------------------------------------------------- /models/base.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | //"fmt" 5 | "github.com/astaxie/beego/config" 6 | //"github.com/astaxie/beego/orm" 7 | _ "github.com/go-sql-driver/mysql" 8 | ) 9 | 10 | // 数据库连接初始化 11 | //func Init() { 12 | // appConf, err := config.NewConfig("ini", "conf/app.conf") 13 | // if err != nil { 14 | // panic(err) 15 | // } 16 | // 17 | // conn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s", 18 | // appConf.String("database::db_user"), 19 | // appConf.String("database::db_passwd"), 20 | // appConf.String("database::db_host"), 21 | // appConf.String("database::db_port"), 22 | // appConf.String("database::db_name"), 23 | // appConf.String("database::db_charset")) 24 | // orm.RegisterDataBase("default", "mysql", conn) 25 | // 26 | // //自动建表 27 | // name := "default" 28 | // err = orm.RunSyncdb(name, false, true) 29 | // if err != nil { 30 | // fmt.Println(err) 31 | // } 32 | // orm.RunCommand() 33 | //} 34 | 35 | //返回带前缀的表名 36 | func TableName(str string) string { 37 | appConf, err := config.NewConfig("ini", "conf/app.conf") 38 | if err != nil { 39 | panic(err) 40 | } 41 | return appConf.String("database::") + str 42 | } 43 | -------------------------------------------------------------------------------- /models/common.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // Predefined model error codes. 4 | const ( 5 | ErrDatabase = -1 6 | ErrSystem = -2 7 | ErrDupRows = -3 8 | ErrNotFound = -4 9 | ) 10 | 11 | type BaseModel struct { 12 | CodeInfo CodeInfo 13 | } 14 | 15 | // CodeInfo definition. 16 | type CodeInfo struct { 17 | Code int `json:"code"` 18 | Info string `json:"info"` 19 | } 20 | 21 | // NewErrorInfo return a CodeInfo represents error. 22 | func NewErrorInfo(info string) *CodeInfo { 23 | return &CodeInfo{-1, info} 24 | } 25 | 26 | // NewSuccessInfo return a CodeInfo represents OK. 27 | func NewSuccessInfo(info string) *CodeInfo { 28 | return &CodeInfo{0, info} 29 | } 30 | -------------------------------------------------------------------------------- /models/device.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/astaxie/beego/orm" 5 | "strings" 6 | "reflect" 7 | "fmt" 8 | "errors" 9 | "time" 10 | ) 11 | 12 | type Device struct { 13 | Id int `json:"id, omitempty" orm:"column(id);pk;unique;auto_increment;int(11)"` 14 | UserId int `json:"user_id" orm:"column(user_id);size(11)"` 15 | DeviceName string `json:"device_name" orm:"column(device_name);unique;size(32)"` 16 | Address string `json:"address" orm:"column(address);size(50)"` 17 | Status int `json:"status" orm:"column(status);size(1)"`// 0: enabled, 1:disabled 18 | CreatedAt int64 `json:"created_at, omitempty" orm:"column(created_at);size(11)"` 19 | UpdatedAt int64 `json:"updated_at, omitempty" orm:"column(updated_at);size(11)"` 20 | Latitude string `json:"latitude, omitempty" orm:"column(latitude);size(12)"` 21 | Longitude string `json:"longitude, omitempty" orm:"column(longitude);size(12)"` 22 | AirAdCount int64 `json:"airad_count, omitempty" orm:"column(airad_count);size(64)"` 23 | //User *User `json:"user_id" orm:"rel(fk)"` 24 | //AirAd []*AirAd `orm:"reverse(many)"` // 设置一对多的反向关系 25 | } 26 | 27 | type DeviceRequestStruct struct { 28 | UserId int `json:"userId"` 29 | Offset int `json:"offset"` 30 | Limit int `json:"limit"` 31 | Fields string `json:"fields"` 32 | } 33 | 34 | func init() { 35 | orm.RegisterModel(new(Device)) 36 | } 37 | 38 | func Devices() orm.QuerySeter { 39 | return orm.NewOrm().QueryTable(new(Device)) 40 | } 41 | 42 | // AddDevice insert a new Device into database and returns 43 | // last inserted Id on success. 44 | func AddDevice(m *Device) (id int64, err error) { 45 | o := orm.NewOrm() 46 | 47 | CreatedAt := time.Now().UTC().Unix() 48 | UpdatedAt := CreatedAt 49 | 50 | device := Device{ 51 | DeviceName:m.DeviceName, 52 | UserId:m.UserId, 53 | Address:m.Address, 54 | Status:m.Status, 55 | CreatedAt:CreatedAt, 56 | UpdatedAt:UpdatedAt, 57 | Latitude:m.Latitude, 58 | Longitude:m.Longitude, 59 | //User *User `json:"user_id" orm:"rel(fk)"` 60 | //AirAd []*AirAd `orm:"reverse(many)"` 61 | } 62 | 63 | //var id int64 64 | id, err = o.Insert(&device) 65 | if err == nil{ 66 | return id, err 67 | } 68 | 69 | return 0, err 70 | } 71 | 72 | // 检测DeviceName是否存在 73 | func CheckDeviceName(deviceName string) bool { 74 | exist := Devices().Filter("DeviceName", deviceName).Exist() 75 | return exist 76 | } 77 | 78 | // GetDeviceById retrieves Device by Id. Returns error if 79 | // Id doesn't exist 80 | func GetDeviceById(id int) (v *Device, err error) { 81 | o := orm.NewOrm() 82 | v = &Device{Id: id} 83 | if err = o.QueryTable(new(Device)).Filter("Id", id).RelatedSel().One(v); err == nil { 84 | return v, nil 85 | } 86 | return nil, err 87 | } 88 | 89 | // GetDeviceByUser retrieves Device by User. Returns error if 90 | // Id doesn't exist 91 | func GetDevicesByUserId(userId int, fields []string, limit int, offset int) (devices []*Device, err error) { 92 | o := orm.NewOrm() 93 | if _, err = o.QueryTable(new(Device)).Filter("user_id", userId).Limit(limit, offset).All(&devices, fields...); err == nil { 94 | return devices, nil 95 | } 96 | return nil, err 97 | } 98 | 99 | // GetAllDevices retrieves all Device matches certain condition. Returns empty list if 100 | // no records exist 101 | func GetAllDevices(query map[string]string, fields []string, sortby []string, order []string, 102 | offset int, limit int, userId int) (ml []interface{}, totalCount int64, err error) { 103 | o := orm.NewOrm() 104 | qs := o.QueryTable(new(Device)) 105 | // query k=v 106 | for k, v := range query { 107 | // rewrite dot-notation to Object__Attribute 108 | k = strings.Replace(k, ".", "__", -1) 109 | qs = qs.Filter(k, v) 110 | } 111 | // order by: 112 | var sortFields []string 113 | if len(sortby) != 0 { 114 | if len(sortby) == len(order) { 115 | // 1) for each sort field, there is an associated order 116 | for i, v := range sortby { 117 | orderby := "" 118 | if order[i] == "desc" { 119 | orderby = "-" + v 120 | } else if order[i] == "asc" { 121 | orderby = v 122 | } else { 123 | return nil, 0, errors.New("Error: Invalid order. Must be either [asc|desc]") 124 | } 125 | sortFields = append(sortFields, orderby) 126 | } 127 | qs = qs.OrderBy(sortFields...) 128 | } else if len(sortby) != len(order) && len(order) == 1 { 129 | // 2) there is exactly one order, all the sorted fields will be sorted by this order 130 | for _, v := range sortby { 131 | orderby := "" 132 | if order[0] == "desc" { 133 | orderby = "-" + v 134 | } else if order[0] == "asc" { 135 | orderby = v 136 | } else { 137 | return nil, 0, errors.New("Error: Invalid order. Must be either [asc|desc]") 138 | } 139 | sortFields = append(sortFields, orderby) 140 | } 141 | } else if len(sortby) != len(order) && len(order) != 1 { 142 | return nil, 0, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1") 143 | } 144 | } else { 145 | if len(order) != 0 { 146 | return nil, 0, errors.New("Error: unused 'order' fields") 147 | } 148 | } 149 | 150 | var l []Device 151 | qs = qs.OrderBy(sortFields...).RelatedSel() 152 | totalCount, err = qs.Filter("UserId", userId).Count() 153 | if _, err = qs.Filter("UserId", userId).Limit(limit, offset).All(&l, fields...); err == nil { 154 | if len(fields) == 0 { 155 | for _, v := range l { 156 | ml = append(ml, v) 157 | } 158 | } else { 159 | // trim unused fields 160 | for _, v := range l { 161 | m := make(map[string]interface{}) 162 | val := reflect.ValueOf(v) 163 | for _, fname := range fields { 164 | m[fname] = val.FieldByName(fname).Interface() 165 | } 166 | ml = append(ml, m) 167 | } 168 | } 169 | return ml, totalCount, nil 170 | } 171 | return nil, 0, err 172 | } 173 | 174 | // UpdateDevice updates Device by Id and returns error if 175 | // the record to be updated doesn't exist 176 | func UpdateDeviceById(m *Device) (err error) { 177 | o := orm.NewOrm() 178 | v := Device{Id: m.Id} 179 | // ascertain id exists in the database 180 | if err = o.Read(&v); err == nil { 181 | var num int64 182 | if num, err = o.Update(m); err == nil { 183 | fmt.Println("Number of records updated in database:", num) 184 | } 185 | } 186 | return 187 | } 188 | 189 | // UpdateDevice updates Device by AirAdCount and returns error if 190 | // the record to be updated doesn't exist 191 | func UpdateDeviceAirAdCount(m *Device) (err error) { 192 | o := orm.NewOrm() 193 | v := Device{Id: m.Id} 194 | m.AirAdCount += 1 195 | // ascertain id exists in the database 196 | if err = o.Read(&v); err == nil { 197 | var num int64 198 | if num, err = o.Update(m); err == nil { 199 | fmt.Println("Number of records updated in database:", num) 200 | } 201 | } 202 | return 203 | } 204 | 205 | 206 | // DeleteDevice deletes Device by Id and returns error if 207 | // the record to be deleted doesn't exist 208 | func DeleteDevice(id int) (err error) { 209 | o := orm.NewOrm() 210 | v := Device{Id: id} 211 | // ascertain id exists in the database 212 | if err = o.Read(&v); err == nil { 213 | var num int64 214 | if num, err = o.Delete(&Device{Id: id}); err == nil { 215 | fmt.Println("Number of records deleted in database:", num) 216 | } 217 | } 218 | return 219 | } -------------------------------------------------------------------------------- /models/messages.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | //"fmt" 5 | "time" 6 | "github.com/astaxie/beego" 7 | "github.com/astaxie/beego/orm" 8 | ) 9 | 10 | type Message struct { 11 | Id int64 `json:"id, omitempty" orm:"column(id);pk;unique;auto_increment"` 12 | UserId int64 `json:"user_id" orm:"column(user_id);size(11)"` 13 | ToUserId int64 `json:"to_user_id" orm:"column(to_user_id);size(11)"` 14 | Type int `json:"type, omitempty" orm:"column(type);size(4)"` 15 | SubType int `json:"sub_type, omitempty" orm:"column(sub_type);size(4)"` 16 | Title string `json:"title, omitempty" orm:"column(title);varbinary"` 17 | Url string `json:"url, omitempty" orm:"column(url);varbinary"` 18 | Viewed int `json:"viewed" orm:"column(viewed);size(1)"`// 1: viewed, 0:not-viewed 19 | CreatedAt int64 `json:"created_at, omitempty" orm:"column(created_at);size(11)"` 20 | } 21 | 22 | func (this *Message) TableName() string { 23 | return TableName("message") 24 | } 25 | func init() { 26 | orm.RegisterModel(new(Message)) 27 | } 28 | 29 | func Messages() orm.QuerySeter { 30 | return orm.NewOrm().QueryTable(new(Message)) 31 | } 32 | 33 | func AddMessages(m * Message)(id int64, err error) { 34 | o := orm.NewOrm() 35 | 36 | message := Message{ 37 | UserId: m.UserId, 38 | ToUserId: m.ToUserId, 39 | Type: m.Type, 40 | SubType: m.SubType, 41 | CreatedAt: time.Now().UTC().Unix(), 42 | Title: m.Title, 43 | Viewed: 0, 44 | Url: m.Url, 45 | } 46 | 47 | //var id int64 48 | id, err = o.Insert(&message) 49 | if err == nil { 50 | return id, err 51 | } 52 | 53 | return 0, err 54 | } 55 | 56 | func ListMessages(query map[string]string, page int, offset int) (msg []interface{}, totalCount int64, err error) { 57 | o := orm.NewOrm() 58 | qs := o.QueryTable(new(Message)) 59 | cond := orm.NewCondition() 60 | 61 | if query["toUserId"] != "" { 62 | cond = cond.And("ToUserId", query["toUserId"]) 63 | } 64 | if query["View"] != "" { 65 | cond = cond.And("View", query["View"]) 66 | } 67 | if query["Type"] != "" { 68 | cond = cond.And("Type", query["type"]) 69 | } 70 | 71 | qs = qs.SetCond(cond) 72 | if page < 1 { 73 | page = 1 74 | } 75 | if offset < 1 { 76 | offset, _ = beego.AppConfig.Int("pageOffset") 77 | } 78 | start := (page - 1) * offset 79 | 80 | 81 | if totalCount, err := qs.Limit(offset, start).All(&msg); err == nil { 82 | return msg, totalCount, nil 83 | } 84 | return nil, 0, err 85 | } 86 | 87 | //统计数量 88 | func CountMessages(query map[string]string) (num int64) { 89 | o := orm.NewOrm() 90 | qs := o.QueryTable(TableName("message")) 91 | cond := orm.NewCondition() 92 | if query["toUserId"] != "" { 93 | cond = cond.And("ToUserId", query["toUserId"]) 94 | } 95 | if query["View"] != "" { 96 | cond = cond.And("View", query["view"]) 97 | } 98 | if query["Type"] != "" { 99 | cond = cond.And("Type", query["type"]) 100 | } 101 | if num, err := qs.SetCond(cond).Count(); err == nil { 102 | return num 103 | } 104 | return 0 105 | } 106 | 107 | func ChangeMessageStatus(id int64, viewed int) (err error) { 108 | o := orm.NewOrm() 109 | v := Message{Id: id} 110 | // ascertain id exists in the database 111 | if err := o.Read(&v); err == nil { 112 | if _, err = o.Update(Message{Viewed:viewed}); err == nil { 113 | return nil 114 | } 115 | } 116 | return err 117 | } 118 | 119 | func ChangeMessageStatusAll(toUserId int64) error { 120 | o := orm.NewOrm() 121 | _, err := o.Raw("UPDATE "+ TableName("message") + " SET Viewed=1 WHERE ToUserId=? AND Viewed=0", toUserId).Exec() 122 | return err 123 | } 124 | 125 | func DeleteMessages(ids string) error { 126 | o := orm.NewOrm() 127 | _, err := o.Raw("DELETE FROM " + TableName("message") + " WHERE id IN(" + ids + ")").Exec() 128 | return err 129 | } -------------------------------------------------------------------------------- /models/mqtt.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "reflect" 7 | "strings" 8 | 9 | "github.com/astaxie/beego/orm" 10 | ) 11 | 12 | type Mqtt struct { 13 | Id int `json:"id, omitempty" orm:"column(id);pk;unique;auto_increment"` 14 | DeviceId int `json:"user_id" orm:"column(device_id);size(11)"` 15 | MqttOptionId int `json:"mqtt_option_id" orm:"column(mqtt_option_id);size(11)"` 16 | // QoS is the QoS of the fixed header. 17 | QoS byte `json:"qos, omitempty" orm:"column(qos);varbinary"` 18 | // Retain is the Retain of the fixed header. 19 | Retain bool `json:"retain, omitempty" orm:"column(retain);varbinary"` 20 | // TopicName is the Topic Name of the variable header. 21 | TopicName string `json:"topic_name, omitempty" orm:"column(topic_name);varbinary"` 22 | // Message is the Application Message of the payload. 23 | //Message []byte 24 | // TopicFilter is the Topic Filter of the Subscription. 25 | TopicFilter string `json:"topic_filter, omitempty" orm:"column(topic_filter);varbinary"` 26 | } 27 | 28 | func init() { 29 | orm.RegisterModel(new(Mqtt)) 30 | } 31 | 32 | func Mqtts() orm.QuerySeter { 33 | return orm.NewOrm().QueryTable(new(Mqtt)) 34 | } 35 | 36 | // AddMqtt insert a new Mqtt into database and returns 37 | // last inserted Id on success. 38 | func AddMqtt(m *Mqtt) (id int64, err error) { 39 | o := orm.NewOrm() 40 | id, err = o.Insert(m) 41 | return 42 | } 43 | 44 | // GetMqttById retrieves Mqtt by Id. Returns error if 45 | // Id doesn't exist 46 | func GetMqttById(id int) (v *Mqtt, err error) { 47 | o := orm.NewOrm() 48 | v = &Mqtt{Id: id} 49 | if err = o.QueryTable(new(Mqtt)).Filter("Id", id).RelatedSel().One(v); err == nil { 50 | return v, nil 51 | } 52 | return nil, err 53 | } 54 | 55 | // GetAllMqtt retrieves all Mqtt matches certain condition. Returns empty list if 56 | // no records exist 57 | func GetAllMqtt(query map[string]string, fields []string, sortby []string, order []string, 58 | offset int64, limit int64) (ml []interface{}, err error) { 59 | o := orm.NewOrm() 60 | qs := o.QueryTable(new(Mqtt)) 61 | // query k=v 62 | for k, v := range query { 63 | // rewrite dot-notation to Object__Attribute 64 | k = strings.Replace(k, ".", "__", -1) 65 | qs = qs.Filter(k, v) 66 | } 67 | // order by: 68 | var sortFields []string 69 | if len(sortby) != 0 { 70 | if len(sortby) == len(order) { 71 | // 1) for each sort field, there is an associated order 72 | for i, v := range sortby { 73 | orderby := "" 74 | if order[i] == "desc" { 75 | orderby = "-" + v 76 | } else if order[i] == "asc" { 77 | orderby = v 78 | } else { 79 | return nil, errors.New("Error: Invalid order. Must be either [asc|desc]") 80 | } 81 | sortFields = append(sortFields, orderby) 82 | } 83 | qs = qs.OrderBy(sortFields...) 84 | } else if len(sortby) != len(order) && len(order) == 1 { 85 | // 2) there is exactly one order, all the sorted fields will be sorted by this order 86 | for _, v := range sortby { 87 | orderby := "" 88 | if order[0] == "desc" { 89 | orderby = "-" + v 90 | } else if order[0] == "asc" { 91 | orderby = v 92 | } else { 93 | return nil, errors.New("Error: Invalid order. Must be either [asc|desc]") 94 | } 95 | sortFields = append(sortFields, orderby) 96 | } 97 | } else if len(sortby) != len(order) && len(order) != 1 { 98 | return nil, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1") 99 | } 100 | } else { 101 | if len(order) != 0 { 102 | return nil, errors.New("Error: unused 'order' fields") 103 | } 104 | } 105 | 106 | var l []Mqtt 107 | qs = qs.OrderBy(sortFields...).RelatedSel() 108 | if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil { 109 | if len(fields) == 0 { 110 | for _, v := range l { 111 | ml = append(ml, v) 112 | } 113 | } else { 114 | // trim unused fields 115 | for _, v := range l { 116 | m := make(map[string]interface{}) 117 | val := reflect.ValueOf(v) 118 | for _, fname := range fields { 119 | m[fname] = val.FieldByName(fname).Interface() 120 | } 121 | ml = append(ml, m) 122 | } 123 | } 124 | return ml, nil 125 | } 126 | return nil, err 127 | } 128 | 129 | // UpdateMqtt updates Mqtt by Id and returns error if 130 | // the record to be updated doesn't exist 131 | func UpdateMqttById(m *Mqtt) (err error) { 132 | o := orm.NewOrm() 133 | v := Mqtt{Id: m.Id} 134 | // ascertain id exists in the database 135 | if err = o.Read(&v); err == nil { 136 | var num int64 137 | if num, err = o.Update(m); err == nil { 138 | fmt.Println("Number of records updated in database:", num) 139 | } 140 | } 141 | return 142 | } 143 | 144 | // DeleteMqtt deletes Mqtt by Id and returns error if 145 | // the record to be deleted doesn't exist 146 | func DeleteMqtt(id int) (err error) { 147 | o := orm.NewOrm() 148 | v := Mqtt{Id: id} 149 | // ascertain id exists in the database 150 | if err = o.Read(&v); err == nil { 151 | var num int64 152 | if num, err = o.Delete(&Mqtt{Id: id}); err == nil { 153 | fmt.Println("Number of records deleted in database:", num) 154 | } 155 | } 156 | return 157 | } 158 | -------------------------------------------------------------------------------- /models/mqttoption.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "reflect" 7 | "strings" 8 | 9 | "github.com/astaxie/beego/orm" 10 | "time" 11 | ) 12 | 13 | type MqttOption struct { 14 | Id int `json:"id, omitempty" orm:"column(id);pk;unique;auto_increment;int(11)"` 15 | // ClientID is the Client Identifier of the payload. 16 | ClientID string `json:"client_id, omitempty" orm:"column(client_id);varbinary"` 17 | // CONNACKTimeout is timeout in seconds for the Client 18 | // to wait for receiving the CONNACK Packet after sending 19 | // the CONNECT Packet. 20 | ConnAckTimeout time.Duration `json:"conn_ack_timeout, omitempty" orm:"column(conn_ack_timeout);size(64)"` 21 | // UserName is the User Name of the payload. 22 | UserName string `json:"user_name, omitempty" orm:"column(user_name);size(32)"` 23 | // Password is the Password of the payload. 24 | Password string `json:"password, omitempty" orm:"column(password);size(128)"` 25 | // CleanSession is the Clean Session of the variable header. 26 | CleanSession bool `json:"clean_session, omitempty" orm:"column(clean_session)"` 27 | // KeepAlive is the Keep Alive of the variable header. 28 | KeepAlive uint16 `json:"keep_alive, omitempty" orm:"column(keep_alive)"` 29 | // WillTopic is the Will Topic of the payload. 30 | WillTopic string `json:"will_topic, omitempty" orm:"column(will_topic);varbinary"` 31 | // WillMessage is the Will Message of the payload. 32 | WillMessage string `json:"will_message, omitempty" orm:"column(will_message);varbinary"` 33 | // WillQoS is the Will QoS of the variable header. 34 | WillQoS bool `json:"will_qos, omitempty" orm:"column(will_qos)"` 35 | // WillRetain is the Will Retain of the variable header. 36 | WillRetain bool `json:"will_retain, omitempty" orm:"column(will_retain)"` 37 | } 38 | 39 | func init() { 40 | orm.RegisterModel(new(MqttOption)) 41 | } 42 | 43 | func MqttOptions() orm.QuerySeter { 44 | return orm.NewOrm().QueryTable(new(MqttOption)) 45 | } 46 | 47 | // AddMqttOption insert a new MqttOption into database and returns 48 | // last inserted Id on success. 49 | func AddMqttOption(m *MqttOption) (id int64, err error) { 50 | o := orm.NewOrm() 51 | id, err = o.Insert(m) 52 | return 53 | } 54 | 55 | // GetMqttOptionById retrieves MqttOption by Id. Returns error if 56 | // Id doesn't exist 57 | func GetMqttOptionById(id int) (v *MqttOption, err error) { 58 | o := orm.NewOrm() 59 | v = &MqttOption{Id: id} 60 | if err = o.QueryTable(new(MqttOption)).Filter("Id", id).RelatedSel().One(v); err == nil { 61 | return v, nil 62 | } 63 | return nil, err 64 | } 65 | 66 | // GetAllMqttOption retrieves all MqttOption matches certain condition. Returns empty list if 67 | // no records exist 68 | func GetAllMqttOption(query map[string]string, fields []string, sortby []string, order []string, 69 | offset int64, limit int64) (ml []interface{}, err error) { 70 | o := orm.NewOrm() 71 | qs := o.QueryTable(new(MqttOption)) 72 | // query k=v 73 | for k, v := range query { 74 | // rewrite dot-notation to Object__Attribute 75 | k = strings.Replace(k, ".", "__", -1) 76 | qs = qs.Filter(k, v) 77 | } 78 | // order by: 79 | var sortFields []string 80 | if len(sortby) != 0 { 81 | if len(sortby) == len(order) { 82 | // 1) for each sort field, there is an associated order 83 | for i, v := range sortby { 84 | orderby := "" 85 | if order[i] == "desc" { 86 | orderby = "-" + v 87 | } else if order[i] == "asc" { 88 | orderby = v 89 | } else { 90 | return nil, errors.New("Error: Invalid order. Must be either [asc|desc]") 91 | } 92 | sortFields = append(sortFields, orderby) 93 | } 94 | qs = qs.OrderBy(sortFields...) 95 | } else if len(sortby) != len(order) && len(order) == 1 { 96 | // 2) there is exactly one order, all the sorted fields will be sorted by this order 97 | for _, v := range sortby { 98 | orderby := "" 99 | if order[0] == "desc" { 100 | orderby = "-" + v 101 | } else if order[0] == "asc" { 102 | orderby = v 103 | } else { 104 | return nil, errors.New("Error: Invalid order. Must be either [asc|desc]") 105 | } 106 | sortFields = append(sortFields, orderby) 107 | } 108 | } else if len(sortby) != len(order) && len(order) != 1 { 109 | return nil, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1") 110 | } 111 | } else { 112 | if len(order) != 0 { 113 | return nil, errors.New("Error: unused 'order' fields") 114 | } 115 | } 116 | 117 | var l []MqttOption 118 | qs = qs.OrderBy(sortFields...).RelatedSel() 119 | if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil { 120 | if len(fields) == 0 { 121 | for _, v := range l { 122 | ml = append(ml, v) 123 | } 124 | } else { 125 | // trim unused fields 126 | for _, v := range l { 127 | m := make(map[string]interface{}) 128 | val := reflect.ValueOf(v) 129 | for _, fname := range fields { 130 | m[fname] = val.FieldByName(fname).Interface() 131 | } 132 | ml = append(ml, m) 133 | } 134 | } 135 | return ml, nil 136 | } 137 | return nil, err 138 | } 139 | 140 | // UpdateMqttOption updates MqttOption by Id and returns error if 141 | // the record to be updated doesn't exist 142 | func UpdateMqttOptionById(m *MqttOption) (err error) { 143 | o := orm.NewOrm() 144 | v := MqttOption{Id: m.Id} 145 | // ascertain id exists in the database 146 | if err = o.Read(&v); err == nil { 147 | var num int64 148 | if num, err = o.Update(m); err == nil { 149 | fmt.Println("Number of records updated in database:", num) 150 | } 151 | } 152 | return 153 | } 154 | 155 | // DeleteMqttOption deletes MqttOption by Id and returns error if 156 | // the record to be deleted doesn't exist 157 | func DeleteMqttOption(id int) (err error) { 158 | o := orm.NewOrm() 159 | v := MqttOption{Id: id} 160 | // ascertain id exists in the database 161 | if err = o.Read(&v); err == nil { 162 | var num int64 163 | if num, err = o.Delete(&MqttOption{Id: id}); err == nil { 164 | fmt.Println("Number of records deleted in database:", num) 165 | } 166 | } 167 | return 168 | } 169 | -------------------------------------------------------------------------------- /models/object.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "errors" 5 | "strconv" 6 | "time" 7 | ) 8 | 9 | var ( 10 | Objects map[string]*Object 11 | ) 12 | 13 | type Object struct { 14 | ObjectId string 15 | Score int64 16 | PlayerName string 17 | } 18 | 19 | func init() { 20 | Objects = make(map[string]*Object) 21 | Objects["hjkhsbnmn123"] = &Object{"hjkhsbnmn123", 100, "astaxie"} 22 | Objects["mjjkxsxsaa23"] = &Object{"mjjkxsxsaa23", 101, "someone"} 23 | } 24 | 25 | func AddOne(object Object) (ObjectId string) { 26 | object.ObjectId = "astaxie" + strconv.FormatInt(time.Now().UnixNano(), 10) 27 | Objects[object.ObjectId] = &object 28 | return object.ObjectId 29 | } 30 | 31 | func GetOne(ObjectId string) (object *Object, err error) { 32 | if v, ok := Objects[ObjectId]; ok { 33 | return v, nil 34 | } 35 | return nil, errors.New("ObjectId Not Exist") 36 | } 37 | 38 | func GetAll() map[string]*Object { 39 | return Objects 40 | } 41 | 42 | func Update(ObjectId string, Score int64) (err error) { 43 | if v, ok := Objects[ObjectId]; ok { 44 | v.Score = Score 45 | return nil 46 | } 47 | return errors.New("ObjectId Not Exist") 48 | } 49 | 50 | func Delete(ObjectId string) { 51 | delete(Objects, ObjectId) 52 | } 53 | 54 | -------------------------------------------------------------------------------- /models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "errors" 5 | "github.com/astaxie/beego/orm" 6 | "reflect" 7 | "strings" 8 | "fmt" 9 | "github.com/rubinliudongpo/airad/utils" 10 | "time" 11 | //"github.com/astaxie/beego" 12 | "github.com/astaxie/beego" 13 | ) 14 | 15 | func (u *User) TableName() string { 16 | return TableName("user") 17 | } 18 | 19 | func init() { 20 | orm.RegisterModel(new(User)) 21 | } 22 | 23 | type User struct { 24 | Id int `json:"id" orm:"column(id);pk;unique;auto_increment;int(11)"` 25 | Username string `json:"username" orm:"column(username);unique;size(32)"` 26 | Password string `json:"password" orm:"column(password);size(128)"` 27 | Avatar string `json:"avatar, omitempty" orm:"column(avatar);varbinary"` 28 | Salt string `json:"salt" orm:"column(salt);size(128)"` 29 | Token string `json:"token" orm:"column(token);size(256)"` 30 | Gender int `json:"gender" orm:"column(gender);size(1)"` // 0:Male, 1: Female, 2: undefined 31 | Age int `json:"age" orm:"column(age):size(3)"` 32 | Address string `json:"address" orm:"column(address);size(50)"` 33 | Email string `json:"email" orm:"column(email);size(50)"` 34 | LastLogin int64 `json:"last_login" orm:"column(last_login);size(11)"` 35 | Status int `json:"status" orm:"column(status);size(1)"`// 0: enabled, 1:disabled 36 | CreatedAt int64 `json:"created_at" orm:"column(created_at);size(11)"` 37 | UpdatedAt int64 `json:"updated_at" orm:"column(updated_at);size(11)"` 38 | DeviceCount int `json:"device_count" orm:"column(device_count);size(64);default(0)"` 39 | //Device []*Device `orm:"reverse(many)"` // 设置一对多的反向关系 40 | } 41 | 42 | func Users() orm.QuerySeter { 43 | return orm.NewOrm().QueryTable(new(User)) 44 | } 45 | 46 | // 检测用户是否存在 47 | func CheckUserId(userId int) bool { 48 | exist := Users().Filter("Id", userId).Exist() 49 | return exist 50 | } 51 | 52 | // 检测用户是否存在 53 | func CheckUserName(username string) bool { 54 | exist := Users().Filter("Username", username).Exist() 55 | return exist 56 | } 57 | 58 | // 检测用户是否存在 59 | func CheckUserIdAndToken(userId int, token string) bool { 60 | exist := Users().Filter("Id", userId).Filter("Token", token).Exist() 61 | return exist 62 | } 63 | 64 | 65 | // 检测用户是否存在 66 | func CheckEmail(email string) bool { 67 | exist := Users().Filter("Email", email).Exist() 68 | return exist 69 | } 70 | 71 | // CheckPass compare input password. 72 | func (u *User) CheckPassword(password string) (ok bool, err error) { 73 | hash, err := utils.GeneratePassHash(password, u.Salt) 74 | if err != nil { 75 | return false, err 76 | } 77 | 78 | return u.Password == hash, nil 79 | } 80 | 81 | // 根据用户ID获取用户 82 | func GetUserById(id int) (v *User, err error) { 83 | o := orm.NewOrm() 84 | v = &User{Id: id} 85 | if err = o.QueryTable(new(User)).Filter("Id", id).RelatedSel().One(v); err == nil { 86 | return v, nil 87 | } 88 | return nil, err 89 | } 90 | 91 | 92 | // 根据用户名字获取用户 93 | func GetUserByUserName(username string) (v *User, err error) { 94 | o := orm.NewOrm() 95 | v = &User{Username: username} 96 | if err = o.QueryTable(new(User)).Filter("Username", username).RelatedSel().One(v); err == nil { 97 | return v, nil 98 | } 99 | return nil, err 100 | } 101 | 102 | // GetAllUser retrieves all User matches certain condition. Returns empty list if 103 | // no records exist 104 | func GetAllUser(query map[string]string, fields []string, sortby []string, order []string, 105 | offset int, limit int) (ml []interface{}, err error) { 106 | o := orm.NewOrm() 107 | qs := o.QueryTable(new(User)) 108 | // query k=v 109 | for k, v := range query { 110 | // rewrite dot-notation to Object__Attribute 111 | k = strings.Replace(k, ".", "__", -1) 112 | qs = qs.Filter(k, v) 113 | } 114 | // order by: 115 | var sortFields []string 116 | if len(sortby) != 0 { 117 | if len(sortby) == len(order) { 118 | // 1) for each sort field, there is an associated order 119 | for i, v := range sortby { 120 | orderby := "" 121 | if order[i] == "desc" { 122 | orderby = "-" + v 123 | } else if order[i] == "asc" { 124 | orderby = v 125 | } else { 126 | return nil, errors.New("Error: Invalid order. Must be either [asc|desc]") 127 | } 128 | sortFields = append(sortFields, orderby) 129 | } 130 | qs = qs.OrderBy(sortFields...) 131 | } else if len(sortby) != len(order) && len(order) == 1 { 132 | // 2) there is exactly one order, all the sorted fields will be sorted by this order 133 | for _, v := range sortby { 134 | orderby := "" 135 | if order[0] == "desc" { 136 | orderby = "-" + v 137 | } else if order[0] == "asc" { 138 | orderby = v 139 | } else { 140 | return nil, errors.New("Error: Invalid order. Must be either [asc|desc]") 141 | } 142 | sortFields = append(sortFields, orderby) 143 | } 144 | } else if len(sortby) != len(order) && len(order) != 1 { 145 | return nil, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1") 146 | } 147 | } else { 148 | if len(order) != 0 { 149 | return nil, errors.New("Error: unused 'order' fields") 150 | } 151 | } 152 | 153 | var l []User 154 | qs = qs.OrderBy(sortFields...).RelatedSel() 155 | if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil { 156 | if len(fields) == 0 { 157 | for _, v := range l { 158 | ml = append(ml, v) 159 | } 160 | } else { 161 | // trim unused fields 162 | for _, v := range l { 163 | m := make(map[string]interface{}) 164 | val := reflect.ValueOf(v) 165 | for _, fname := range fields { 166 | m[fname] = val.FieldByName(fname).Interface() 167 | } 168 | ml = append(ml, m) 169 | } 170 | } 171 | return ml, nil 172 | } 173 | return nil, err 174 | } 175 | 176 | func GetUserByToken(token string) (bool, User) { 177 | o := orm.NewOrm() 178 | var user User 179 | err := o.QueryTable(user).Filter("Token", token).One(&user) 180 | return err != orm.ErrNoRows, user 181 | } 182 | 183 | func Login(username string, password string) (bool, *User) { 184 | o := orm.NewOrm() 185 | user, err := GetUserByUserName(username) 186 | if err != nil { 187 | return false, nil 188 | } 189 | passwordHash, err := utils.GeneratePassHash(password, user.Salt) 190 | if err != nil { 191 | return false, nil 192 | } 193 | err = o.QueryTable(user).Filter("Username", username).Filter("Password", passwordHash).One(user) 194 | return err != orm.ErrNoRows, user 195 | 196 | } 197 | 198 | func GetUserByUsername(username string) (err error, user *User) { 199 | o := orm.NewOrm() 200 | user = &User{Username: username} 201 | if err := o.QueryTable(user).Filter("Username", username).One(&user); err == nil { 202 | return nil, user 203 | } 204 | return err, nil 205 | } 206 | 207 | func AddUser(m *User) (*User, error) { 208 | o := orm.NewOrm() 209 | salt, err := utils.GenerateSalt() 210 | if err != nil { 211 | return nil, err 212 | } 213 | 214 | passwordHash, err := utils.GeneratePassHash(m.Password, salt) 215 | if err != nil { 216 | return nil, err 217 | } 218 | CreatedAt := time.Now().UTC().Unix() 219 | UpdatedAt := CreatedAt 220 | LastLogin := CreatedAt 221 | 222 | et := utils.EasyToken{ 223 | Username: m.Username, 224 | Uid: 0, 225 | Expires: time.Now().Unix() + 2 * 3600, 226 | } 227 | token, err := et.GetToken() 228 | user := User{ 229 | Username:m.Username, 230 | Password: passwordHash, 231 | Salt:salt, 232 | Token:token, 233 | Gender:m.Gender, 234 | Age:m.Age, 235 | Address:m.Address, 236 | Email:m.Email, 237 | LastLogin:LastLogin, 238 | Status:m.Status, 239 | CreatedAt:CreatedAt, 240 | UpdatedAt:UpdatedAt, 241 | } 242 | _, err = o.Insert(&user) 243 | if err == nil{ 244 | return &user, err 245 | } 246 | 247 | return nil, err 248 | } 249 | 250 | func UpdateUser(user *User) { 251 | o := orm.NewOrm() 252 | o.Update(user) 253 | } 254 | 255 | // UpdateDevice updates User by DeviceCount and returns error if 256 | // the record to be updated doesn't exist 257 | func UpdateUserDeviceCount(m *User) (err error) { 258 | o := orm.NewOrm() 259 | v := User{Id: m.Id} 260 | m.DeviceCount += 1 261 | // ascertain id exists in the database 262 | if err = o.Read(&v); err == nil { 263 | var num int64 264 | if num, err = o.Update(m); err == nil { 265 | fmt.Println("Number of records updated in database:", num) 266 | } 267 | } 268 | return 269 | } 270 | 271 | // updates User's Token and returns error if 272 | // the record to be updated doesn't exist 273 | func UpdateUserToken(m *User, token string) (err error) { 274 | o := orm.NewOrm() 275 | v := User{Id: m.Id} 276 | m.Token = token 277 | // ascertain id exists in the database 278 | if err = o.Read(&v); err == nil { 279 | var num int64 280 | if num, err = o.Update(m); err == nil { 281 | fmt.Println("Number of records updated in database:", num) 282 | } 283 | } 284 | return err 285 | } 286 | 287 | // updates User's LastLogin and returns error if 288 | // the record to be updated doesn't exist 289 | func UpdateUserLastLogin(m *User) (err error) { 290 | o := orm.NewOrm() 291 | v := User{Id: m.Id} 292 | lastLogin := time.Now().UTC().Unix() 293 | m.LastLogin = lastLogin 294 | // ascertain id exists in the database 295 | if err = o.Read(&v); err == nil { 296 | var num int64 297 | if num, err = o.Update(m); err == nil { 298 | fmt.Println("Number of records updated in database:", num) 299 | } 300 | } 301 | return err 302 | } 303 | 304 | // UpdateUser updates User by Id and returns error if 305 | // the record to be updated doesn't exist 306 | func UpdateUserById(m *User) (err error) { 307 | o := orm.NewOrm() 308 | v := User{Id: m.Id} 309 | // ascertain id exists in the database 310 | if err = o.Read(&v); err == nil { 311 | var num int64 312 | if num, err = o.Update(m); err == nil { 313 | fmt.Println("Number of records updated in database:", num) 314 | } 315 | } 316 | return 317 | } 318 | 319 | // DeleteUser deletes User by Id and returns error if 320 | // the record to be deleted doesn't exist 321 | func DeleteUser(id int) (err error) { 322 | o := orm.NewOrm() 323 | v := User{Id: id} 324 | // ascertain id exists in the database 325 | if err = o.Read(&v); err == nil { 326 | var num int64 327 | if num, err = o.Delete(&AirAd{Id: id}); err == nil { 328 | fmt.Println("Number of records deleted in database:", num) 329 | } 330 | } 331 | return 332 | } 333 | 334 | 335 | func GetUsername(id int) string { 336 | var err error 337 | var username string 338 | 339 | err = utils.GetCache("GetUsername.id."+fmt.Sprintf("%d", id), &username) 340 | if err != nil { 341 | cacheExpire, _ := beego.AppConfig.Int("cache_expire") 342 | var user User 343 | o := orm.NewOrm() 344 | o.QueryTable(TableName("user")).Filter("Id", id).One(&user, "username") 345 | username = user.Username 346 | utils.SetCache("GetRealname.id."+fmt.Sprintf("%d", id), username, cacheExpire) 347 | } 348 | return username 349 | } 350 | 351 | //func HashPassword(password string) (string, error) { 352 | // bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14) 353 | // return string(bytes), err 354 | //} 355 | // 356 | //func CheckPasswordHash(password, hash string) bool { 357 | // err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) 358 | // return err == nil 359 | //} 360 | 361 | 362 | 363 | //func generateToken() (tokenString string, err error) { 364 | // /* Create the token */ 365 | // token := jwt.New(jwt.SigningMethodHS256) 366 | // 367 | // /* Create a map to store our claims 368 | // claims := token.Claims.(jwt.MapClaims) 369 | // 370 | // /* Set token claims */ 371 | // claims["admin"] = true 372 | // claims["name"] = "Ado Kukic" 373 | // claims["exp"] = time.Now().Add(time.Hour * 24).Unix() 374 | // 375 | // /* Sign the token with our secret */ 376 | // tokenString, _ := token.SignedString(mySigningKey) 377 | //} -------------------------------------------------------------------------------- /pictures/airad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubinliudongpo/airad/3968aa1f7cefb098976544aa463db6535204f15a/pictures/airad.png -------------------------------------------------------------------------------- /pictures/airad_swagger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubinliudongpo/airad/3968aa1f7cefb098976544aa463db6535204f15a/pictures/airad_swagger.png -------------------------------------------------------------------------------- /routers/router.go: -------------------------------------------------------------------------------- 1 | // @APIVersion 1.0.0 2 | // @Title beego Test API 3 | // @Description beego has a very cool tools to autogenerate documents for your API 4 | // @Contact astaxie@gmail.com 5 | // @TermsOfServiceUrl http://beego.me/ 6 | // @License Apache 2.0 7 | // @LicenseUrl http://www.apache.org/licenses/LICENSE-2.0.html 8 | package routers 9 | 10 | import ( 11 | "github.com/astaxie/beego" 12 | 13 | "github.com/rubinliudongpo/airad/controllers" 14 | ) 15 | 16 | func init() { 17 | beego.Router("/", &controllers.MainController{}) 18 | beego.Router("/login", &controllers.UserController{}, "post:Login") 19 | ns := beego.NewNamespace("/v1", 20 | beego.NSNamespace("/user", beego.NSInclude(&controllers.UserController{},),), 21 | beego.NSNamespace("/airad", beego.NSInclude(&controllers.AirAdController{},),), 22 | beego.NSNamespace("/device", beego.NSInclude(&controllers.DeviceController{},),), 23 | ) 24 | beego.AddNamespace(ns) 25 | //beego.InsertFilter("/permission/list", beego.BeforeRouter, filters.HasPermission) 26 | beego.Router("/v1/device/getdevicebyuserid", &controllers.DeviceController{}, "POST:GetDevicesByUserId") 27 | } 28 | -------------------------------------------------------------------------------- /swagger/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubinliudongpo/airad/3968aa1f7cefb098976544aa463db6535204f15a/swagger/favicon-16x16.png -------------------------------------------------------------------------------- /swagger/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubinliudongpo/airad/3968aa1f7cefb098976544aa463db6535204f15a/swagger/favicon-32x32.png -------------------------------------------------------------------------------- /swagger/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |
71 | Beego is a simple & powerful Go web framework which is inspired by tornado and sinatra.
72 |
73 | Official website: {{.Website}}
74 |
75 | Contact me: {{.Email}}
76 |