github.com/weplanx/server@v0.2.6-0.20240318110640-f7e75155779a/api/api.go (about) 1 package api 2 3 import ( 4 "context" 5 "fmt" 6 "github.com/cloudwego/hertz/pkg/app" 7 "github.com/cloudwego/hertz/pkg/app/server" 8 "github.com/cloudwego/hertz/pkg/common/hlog" 9 "github.com/cloudwego/hertz/pkg/common/utils" 10 "github.com/google/wire" 11 "github.com/nats-io/nats.go" 12 transfer "github.com/weplanx/collector/client" 13 "github.com/weplanx/go/csrf" 14 "github.com/weplanx/go/passport" 15 "github.com/weplanx/go/rest" 16 "github.com/weplanx/go/sessions" 17 "github.com/weplanx/go/values" 18 "github.com/weplanx/server/api/acc_tasks" 19 "github.com/weplanx/server/api/builders" 20 "github.com/weplanx/server/api/clusters" 21 "github.com/weplanx/server/api/datasets" 22 "github.com/weplanx/server/api/endpoints" 23 "github.com/weplanx/server/api/imessages" 24 "github.com/weplanx/server/api/index" 25 "github.com/weplanx/server/api/lark" 26 "github.com/weplanx/server/api/monitor" 27 "github.com/weplanx/server/api/projects" 28 "github.com/weplanx/server/api/queues" 29 "github.com/weplanx/server/api/tencent" 30 "github.com/weplanx/server/api/workflows" 31 "github.com/weplanx/server/common" 32 "time" 33 ) 34 35 var Provides = wire.NewSet( 36 wire.Struct(new(values.Controller), "*"), 37 wire.Struct(new(sessions.Controller), "*"), 38 wire.Struct(new(rest.Controller), "*"), 39 index.Provides, 40 tencent.Provides, 41 lark.Provides, 42 projects.Provides, 43 clusters.Provides, 44 endpoints.Provides, 45 acc_tasks.Provides, 46 datasets.Provides, 47 monitor.Provides, 48 imessages.Provides, 49 queues.Provides, 50 workflows.Provides, 51 builders.Provides, 52 ) 53 54 type API struct { 55 *common.Inject 56 57 Hertz *server.Hertz 58 Csrf *csrf.Csrf 59 Values *values.Controller 60 Sessions *sessions.Controller 61 Rest *rest.Controller 62 Index *index.Controller 63 IndexX *index.Service 64 Tencent *tencent.Controller 65 TencentX *tencent.Service 66 Lark *lark.Controller 67 LarkX *lark.Service 68 Projects *projects.Controller 69 ProjectsX *projects.Service 70 Clusters *clusters.Controller 71 ClustersX *clusters.Service 72 Endpoints *endpoints.Controller 73 EndpointsX *endpoints.Service 74 Workflows *workflows.Controller 75 WorkflowsX *workflows.Service 76 Queues *queues.Controller 77 QueuesX *queues.Service 78 Imessages *imessages.Controller 79 ImessagesX *imessages.Service 80 AccTasks *acc_tasks.Controller 81 AccTasksX *acc_tasks.Service 82 Datasets *datasets.Controller 83 DatasetsX *datasets.Service 84 Monitor *monitor.Controller 85 MonitorX *monitor.Service 86 Builders *builders.Controller 87 BuildersX *builders.Service 88 } 89 90 func (x *API) Routes(h *server.Hertz) (err error) { 91 csrfToken := x.Csrf.VerifyToken(!x.V.IsRelease()) 92 auth := x.AuthGuard() 93 audit := x.Audit() 94 95 h.GET("", x.Index.Ping) 96 _login := h.Group("login", csrfToken) 97 { 98 _login.POST("", x.Index.Login) 99 _login.GET("sms", x.Index.GetLoginSms) 100 _login.POST("sms", x.Index.LoginSms) 101 _login.POST("totp", x.Index.LoginTotp) 102 } 103 h.GET("forget_code", x.Index.GetForgetCode) 104 h.POST("forget_reset", csrfToken, x.Index.ForgetReset) 105 h.GET("verify", csrfToken, x.Index.Verify) 106 h.GET("refresh_code", csrfToken, auth, x.Index.GetRefreshCode) 107 h.POST("refresh_token", csrfToken, auth, x.Index.RefreshToken) 108 h.POST("logout", csrfToken, auth, x.Index.Logout) 109 h.GET("options", x.Index.Options) 110 111 m := []app.HandlerFunc{csrfToken, auth, audit} 112 _user := h.Group("user", m...) 113 { 114 _user.GET("", x.Index.GetUser) 115 _user.PATCH("", x.Index.SetUser) 116 _user.POST("password", x.Index.SetUserPassword) 117 _user.GET("phone_code", x.Index.GetUserPhoneCode) 118 _user.POST("phone", x.Index.SetUserPhone) 119 _user.GET("totp", x.Index.GetUserTotp) 120 _user.POST("totp", x.Index.SetUserTotp) 121 _user.DELETE(":key", x.Index.UnsetUser) 122 } 123 _values := h.Group("values", m...) 124 { 125 _values.GET("", x.Values.Get) 126 _values.PATCH("", x.Values.Set) 127 _values.DELETE(":key", x.Values.Remove) 128 } 129 _sessions := h.Group("sessions", m...) 130 { 131 _sessions.GET("", x.Sessions.Lists) 132 _sessions.DELETE(":uid", x.Sessions.Remove) 133 _sessions.POST("clear", x.Sessions.Clear) 134 } 135 _db := h.Group("db", csrfToken, auth) 136 { 137 _db.GET(":collection/:id", x.Rest.FindById) 138 _db.POST(":collection/create", audit, x.Rest.Create) 139 _db.POST(":collection/bulk_create", audit, x.Rest.BulkCreate) 140 _db.POST(":collection/size", x.Rest.Size) 141 _db.POST(":collection/find", x.Rest.Find) 142 _db.POST(":collection/find_one", x.Rest.FindOne) 143 _db.POST(":collection/update", audit, x.Rest.Update) 144 _db.POST(":collection/bulk_delete", audit, x.Rest.BulkDelete) 145 _db.POST(":collection/sort", audit, x.Rest.Sort) 146 _db.PATCH(":collection/:id", audit, x.Rest.UpdateById) 147 _db.PUT(":collection/:id", audit, x.Rest.Replace) 148 _db.DELETE(":collection/:id", audit, x.Rest.Delete) 149 _db.POST("transaction", audit, x.Rest.Transaction) 150 _db.POST("commit", audit, x.Rest.Commit) 151 } 152 _tencent := h.Group("tencent", m...) 153 { 154 _tencent.GET("cos_presigned", x.Tencent.CosPresigned) 155 _tencent.GET("cos_image_info", x.Tencent.CosImageInfo) 156 } 157 h.POST("lark", x.Lark.Challenge) 158 h.GET("lark", x.Lark.OAuth) 159 _lark := h.Group("lark", m...) 160 { 161 _lark.POST("tasks", x.Lark.CreateTasks) 162 _lark.GET("tasks", x.Lark.GetTasks) 163 } 164 _projects := h.Group("projects", m...) 165 { 166 _projects.GET(":id/tenants", x.Projects.GetTenants) 167 _projects.POST("deploy_nats", x.Projects.DeployNats) 168 } 169 _clusters := h.Group("clusters", m...) 170 { 171 _clusters.GET(":id/info", x.Clusters.GetInfo) 172 _clusters.GET(":id/nodes", x.Clusters.GetNodes) 173 } 174 _endpoints := h.Group("endpoints", m...) 175 { 176 _endpoints.GET(":id/schedule_keys", x.Endpoints.ScheduleKeys) 177 _endpoints.POST("schedule_ping", x.Endpoints.SchedulePing) 178 _endpoints.POST("schedule_revoke", x.Endpoints.ScheduleRevoke) 179 _endpoints.POST("schedule_state", x.Endpoints.ScheduleState) 180 } 181 _workflows := h.Group("workflows", m...) 182 { 183 _workflows.POST("sync", x.Workflows.Sync) 184 } 185 _queues := h.Group("queues", m...) 186 { 187 _queues.POST("sync", x.Queues.Sync) 188 _queues.GET(":id/info", x.Queues.Info) 189 _queues.POST("publish", x.Queues.Publish) 190 } 191 _builders := h.Group("builders", m...) 192 { 193 _builders.POST("sort_fields", x.Builders.SortFields) 194 } 195 _imessages := h.Group("imessages", m...) 196 { 197 _imessages.GET("nodes", x.Imessages.GetNodes) 198 _imessages.PUT(":id/rule", x.Imessages.UpdateRule) 199 _imessages.DELETE(":id/rule", x.Imessages.DeleteRule) 200 _imessages.GET(":id/metrics", x.Imessages.GetMetrics) 201 _imessages.PUT(":id/metrics", x.Imessages.UpdateMetrics) 202 _imessages.DELETE(":id/metrics", x.Imessages.DeleteMetrics) 203 _imessages.POST("publish", x.Imessages.Publish) 204 } 205 _accTasks := h.Group("acc_tasks", m...) 206 { 207 _accTasks.POST("invoke", x.AccTasks.Invoke) 208 } 209 _datasets := h.Group("datasets", m...) 210 { 211 _datasets.GET("", x.Datasets.Lists) 212 _datasets.POST("create", x.Datasets.Create) 213 _datasets.DELETE(":name", x.Datasets.Delete) 214 } 215 if *x.V.Influx.Enabled { 216 _monitor := h.Group("monitor", m...) 217 { 218 _monitor.GET(":name", x.Monitor.Exporters) 219 } 220 } 221 return 222 } 223 224 func (x *API) AuthGuard() app.HandlerFunc { 225 return func(ctx context.Context, c *app.RequestContext) { 226 ts := c.Cookie("TOKEN") 227 if ts == nil { 228 c.AbortWithStatusJSON(401, utils.H{ 229 "code": 0, 230 "message": "authentication has expired, please log in again", 231 }) 232 return 233 } 234 235 claims, err := x.IndexX.Verify(ctx, string(ts)) 236 if err != nil { 237 common.ClearAccessToken(c) 238 c.AbortWithStatusJSON(401, utils.H{ 239 "code": 0, 240 "message": common.ErrAuthenticationExpired.Error(), 241 }) 242 return 243 } 244 245 c.Set("identity", claims) 246 c.Next(ctx) 247 } 248 } 249 250 func (x *API) Audit() app.HandlerFunc { 251 return func(ctx context.Context, c *app.RequestContext) { 252 now := time.Now() 253 c.Next(ctx) 254 method := string(c.Request.Header.Method()) 255 if method == "GET" { 256 return 257 } 258 var userId string 259 if value, ok := c.Get("identity"); ok { 260 claims := value.(passport.Claims) 261 userId = claims.UserId 262 } 263 264 format := map[string]interface{}{ 265 "body": "json", 266 } 267 if userId != "" { 268 format["metadata.user_id"] = "oid" 269 } 270 transferCtx, cancel := context.WithTimeout(context.Background(), time.Second*10) 271 defer cancel() 272 273 x.Transfer.Publish(transferCtx, "logset_operates", transfer.Payload{ 274 Timestamp: now, 275 Data: map[string]interface{}{ 276 "metadata": map[string]interface{}{ 277 "method": method, 278 "path": string(c.Request.Path()), 279 "user_id": userId, 280 "client_ip": c.ClientIP(), 281 }, 282 "params": string(c.Request.QueryString()), 283 "body": c.Request.Body(), 284 "status": c.Response.StatusCode(), 285 }, 286 XData: format, 287 }) 288 } 289 } 290 291 func (x *API) Initialize(ctx context.Context) (h *server.Hertz, err error) { 292 h = x.Hertz 293 294 update := make(chan interface{}) 295 go x.Values.Service.Sync(x.V.Extra, update) 296 go x.ValuesChange(update) 297 298 if err = x.Transfer.Set(ctx, transfer.StreamOption{ 299 Key: "logset_operates", 300 }); err != nil { 301 return 302 } 303 304 go func() { 305 if err = x.WorkflowsX.Event(); err != nil { 306 hlog.Error(err) 307 } 308 if err = x.QueuesX.Event(); err != nil { 309 hlog.Error(err) 310 } 311 if err = x.ImessagesX.Event(); err != nil { 312 hlog.Error(err) 313 } 314 }() 315 316 return 317 } 318 319 func (x *API) ValuesChange(ok chan interface{}) { 320 for range ok { 321 for k, v := range x.V.RestControls { 322 if v.Event { 323 if _, err := x.JetStream.AddStream(&nats.StreamConfig{ 324 Name: fmt.Sprintf(`EVENT_%s`, k), 325 Subjects: []string{fmt.Sprintf(`events.%s`, k)}, 326 Retention: nats.WorkQueuePolicy, 327 }); err != nil { 328 hlog.Error(err) 329 } 330 } 331 } 332 } 333 return 334 }