github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/cmd/srv-applet-mgr/apis/middleware/current_user.go (about) 1 package middleware 2 3 import ( 4 "context" 5 "reflect" 6 7 "github.com/machinefi/w3bstream/pkg/depends/kit/httptransport/httpx" 8 "github.com/machinefi/w3bstream/pkg/depends/kit/logr" 9 "github.com/machinefi/w3bstream/pkg/depends/kit/statusx" 10 "github.com/machinefi/w3bstream/pkg/depends/x/misc/must" 11 "github.com/machinefi/w3bstream/pkg/enums" 12 "github.com/machinefi/w3bstream/pkg/errors/status" 13 "github.com/machinefi/w3bstream/pkg/models" 14 "github.com/machinefi/w3bstream/pkg/modules/account" 15 "github.com/machinefi/w3bstream/pkg/modules/applet" 16 "github.com/machinefi/w3bstream/pkg/modules/blockchain" 17 "github.com/machinefi/w3bstream/pkg/modules/cronjob" 18 "github.com/machinefi/w3bstream/pkg/modules/deploy" 19 "github.com/machinefi/w3bstream/pkg/modules/operator" 20 "github.com/machinefi/w3bstream/pkg/modules/project" 21 "github.com/machinefi/w3bstream/pkg/modules/publisher" 22 "github.com/machinefi/w3bstream/pkg/modules/resource" 23 "github.com/machinefi/w3bstream/pkg/modules/strategy" 24 "github.com/machinefi/w3bstream/pkg/modules/trafficlimit" 25 "github.com/machinefi/w3bstream/pkg/types" 26 ) 27 28 type ContextAccountAuth struct { 29 httpx.MethodGet 30 } 31 32 var contextAccountAuthKey = reflect.TypeOf(ContextAccountAuth{}).String() 33 34 func (r *ContextAccountAuth) ContextKey() string { return contextAccountAuthKey } 35 36 func (r *ContextAccountAuth) Output(ctx context.Context) (interface{}, error) { 37 ctx, l := logr.Start(ctx, "api.mw.ContextAccountAuth") 38 defer l.End() 39 40 pl, err := ParseJwtAuthContentFromContext(ctx) 41 if err != nil { 42 return nil, status.InvalidAuthAccountID.StatusErr().WithDesc(err.Error()) 43 } 44 45 switch pl.IdentityType { 46 // must unknown or account 47 case enums.ACCESS_KEY_IDENTITY_TYPE__ACCOUNT, enums.ACCESS_KEY_IDENTITY_TYPE_UNKNOWN: 48 ca, err := account.GetAccountByAccountID(ctx, pl.IdentityID) 49 if err != nil { 50 return nil, err 51 } 52 return &CurrentAccount{*ca}, nil 53 default: 54 return nil, status.InvalidAuthValue 55 } 56 } 57 58 func MustCurrentAccountFromContext(ctx context.Context) *CurrentAccount { 59 ca, ok := ctx.Value(contextAccountAuthKey).(*CurrentAccount) 60 must.BeTrue(ok) 61 return ca 62 } 63 64 func CurrentAccountFromContext(ctx context.Context) (*CurrentAccount, bool) { 65 ca, ok := ctx.Value(contextAccountAuthKey).(*CurrentAccount) 66 return ca, ok 67 } 68 69 type CurrentAccount struct { 70 models.Account 71 } 72 73 func (v *CurrentAccount) CheckRole(role enums.AccountRole) (*CurrentAccount, bool) { 74 if v.Role == role { 75 return v, true 76 } 77 return nil, false 78 } 79 80 func (v *CurrentAccount) WithAccount(ctx context.Context) context.Context { 81 return types.WithAccount(ctx, &v.Account) 82 } 83 84 // WithProjectContextByName With project context by project name(in database) 85 func (v *CurrentAccount) WithProjectContextByName(ctx context.Context, name string) (context.Context, error) { 86 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithProjectContextByName") 87 defer l.End() 88 89 prj, err := project.GetByName(ctx, name) 90 if err != nil { 91 return nil, err 92 } 93 if v.Role == enums.ACCOUNT_ROLE__ADMIN || v.AccountID == prj.AccountID { 94 return types.WithProject(ctx, prj), nil 95 } 96 97 return nil, status.NoProjectPermission 98 } 99 100 // WithProjectContextBySFID With project context by project SFID 101 func (v *CurrentAccount) WithProjectContextBySFID(ctx context.Context, id types.SFID) (context.Context, error) { 102 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithProjectContextBySFID") 103 defer l.End() 104 105 prj, err := project.GetBySFID(ctx, id) 106 if err != nil { 107 return nil, err 108 } 109 if v.Role == enums.ACCOUNT_ROLE__ADMIN || v.AccountID == prj.AccountID { 110 return types.WithProject(ctx, prj), nil 111 } 112 113 return nil, status.NoProjectPermission 114 } 115 116 // WithAppletContextBySFID With applet contexts by applet SFID 117 func (v *CurrentAccount) WithAppletContextBySFID(ctx context.Context, id types.SFID) (context.Context, error) { 118 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithAppletContextBySFID") 119 defer l.End() 120 121 app, err := applet.GetBySFID(ctx, id) 122 if err != nil { 123 return nil, err 124 } 125 ctx = types.WithApplet(ctx, app) 126 127 ctx, err = v.WithProjectContextBySFID(ctx, app.ProjectID) 128 if err != nil { 129 return nil, err 130 } 131 132 ins, err := deploy.GetByAppletSFID(ctx, app.AppletID) 133 if err != nil { 134 se, ok := statusx.IsStatusErr(err) 135 if !ok || !se.Is(status.InstanceNotFound) { 136 return nil, err 137 } 138 } else { 139 ctx = types.WithInstance(ctx, ins) 140 } 141 142 return ctx, nil 143 } 144 145 func (v *CurrentAccount) WithResourceContextBySFID(ctx context.Context, id types.SFID) (context.Context, error) { 146 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithResourceContextBySFID") 147 defer l.End() 148 149 res, err := resource.GetBySFID(ctx, id) 150 if err != nil { 151 return nil, err 152 } 153 154 return types.WithResource(ctx, res), nil 155 } 156 157 // WithInstanceContextBySFID With full contexts by instance SFID 158 func (v *CurrentAccount) WithInstanceContextBySFID(ctx context.Context, id types.SFID) (context.Context, error) { 159 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithInstanceContextBySFID") 160 defer l.End() 161 162 var ( 163 ins *models.Instance 164 app *models.Applet 165 res *models.Resource 166 err error 167 ) 168 if ins, err = deploy.GetBySFID(ctx, id); err != nil { 169 return nil, err 170 } 171 ctx = types.WithInstance(ctx, ins) 172 173 if app, err = applet.GetBySFID(ctx, ins.AppletID); err != nil { 174 return nil, err 175 } 176 ctx = types.WithApplet(ctx, app) 177 178 if ctx, err = v.WithProjectContextBySFID(ctx, app.ProjectID); err != nil { 179 return nil, err 180 } 181 182 if res, err = resource.GetBySFID(ctx, app.ResourceID); err != nil { 183 return nil, err 184 } 185 return types.WithResource(ctx, res), nil 186 } 187 188 func (v *CurrentAccount) WithStrategyBySFID(ctx context.Context, id types.SFID) (context.Context, error) { 189 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithStrategyBySFID") 190 defer l.End() 191 192 sty, err := strategy.GetBySFID(ctx, id) 193 if err != nil { 194 return nil, err 195 } 196 ctx = types.WithStrategy(ctx, sty) 197 return v.WithProjectContextBySFID(ctx, sty.ProjectID) 198 } 199 200 func (v *CurrentAccount) WithPublisherBySFID(ctx context.Context, id types.SFID) (context.Context, error) { 201 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithPublisherBySFID") 202 defer l.End() 203 204 pub, err := publisher.GetBySFID(ctx, id) 205 if err != nil { 206 return nil, err 207 } 208 ctx = types.WithPublisher(ctx, pub) 209 return v.WithProjectContextBySFID(ctx, pub.ProjectID) 210 } 211 212 func (v *CurrentAccount) WithResourceOwnerContextBySFID(ctx context.Context, id types.SFID) (context.Context, error) { 213 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithResourceOwnerContextBySFID") 214 defer l.End() 215 216 ship, err := resource.GetOwnerByAccountAndSFID(ctx, v.AccountID, id) 217 if err != nil { 218 return nil, err 219 } 220 if v.Role == enums.ACCOUNT_ROLE__ADMIN || v.AccountID == ship.AccountID { 221 return types.WithResourceOwnership(ctx, ship), nil 222 } 223 224 return nil, status.NoResourcePermission 225 } 226 227 func (v *CurrentAccount) WithCronJobBySFID(ctx context.Context, id types.SFID) (context.Context, error) { 228 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithCronJobBySFID") 229 defer l.End() 230 231 cronJob, err := cronjob.GetBySFID(ctx, id) 232 if err != nil { 233 return nil, err 234 } 235 ctx = types.WithCronJob(ctx, cronJob) 236 return v.WithProjectContextBySFID(ctx, cronJob.ProjectID) 237 } 238 239 func (v *CurrentAccount) WithOperatorBySFID(ctx context.Context, id types.SFID) (context.Context, error) { 240 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithOperatorBySFID") 241 defer l.End() 242 243 op, err := operator.GetBySFID(ctx, id) 244 if err != nil { 245 return nil, err 246 } 247 if v.AccountID != op.AccountID { 248 return nil, status.NoOperatorPermission 249 } 250 return types.WithOperator(ctx, op), nil 251 } 252 253 func (v *CurrentAccount) WithContractLogBySFID(ctx context.Context, id types.SFID) (context.Context, error) { 254 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithContractLogBySFID") 255 defer l.End() 256 257 cl, err := blockchain.GetContractLogBySFID(ctx, id) 258 if err != nil { 259 return nil, err 260 } 261 ctx = types.WithContractLog(ctx, cl) 262 return v.WithProjectContextByName(ctx, cl.ProjectName) 263 } 264 265 func (v *CurrentAccount) WithChainHeightBySFID(ctx context.Context, id types.SFID) (context.Context, error) { 266 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithChainHeightBySFID") 267 defer l.End() 268 269 h, err := blockchain.GetChainHeightBySFID(ctx, id) 270 if err != nil { 271 return nil, err 272 } 273 ctx = types.WithChainHeight(ctx, h) 274 return v.WithProjectContextByName(ctx, h.ProjectName) 275 } 276 277 func (v *CurrentAccount) WithChainTxBySFID(ctx context.Context, id types.SFID) (context.Context, error) { 278 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithChainTxBySFID") 279 defer l.End() 280 281 t, err := blockchain.GetChainTxBySFID(ctx, id) 282 if err != nil { 283 return nil, err 284 } 285 ctx = types.WithChainTx(ctx, t) 286 return v.WithProjectContextByName(ctx, t.ProjectName) 287 } 288 289 func (v *CurrentAccount) WithTrafficLimitContextBySFID(ctx context.Context, id types.SFID) (context.Context, error) { 290 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithTrafficLimitContextBySFID") 291 defer l.End() 292 293 traffic, err := trafficlimit.GetBySFID(ctx, id) 294 if err != nil { 295 return nil, err 296 } 297 ctx = types.WithTrafficLimit(ctx, traffic) 298 return v.WithProjectContextBySFID(ctx, traffic.ProjectID) 299 } 300 301 func (v *CurrentAccount) WithTrafficLimitContextBySFIDAndProjectName(ctx context.Context, id types.SFID) (context.Context, error) { 302 ctx, l := logr.Start(ctx, "api.mw.CurrentAccount.WithTrafficLimitContextBySFIDAndProjectName") 303 defer l.End() 304 305 traffic, err := trafficlimit.GetBySFID(ctx, id) 306 if err != nil { 307 return nil, err 308 } 309 project := types.MustProjectFromContext(ctx) 310 if v.Role == enums.ACCOUNT_ROLE__ADMIN || traffic.ProjectID == project.ProjectID { 311 return types.WithTrafficLimit(ctx, traffic), nil 312 } 313 314 return nil, status.NoProjectPermission 315 }