GraphQL API and utilities for the rpdata project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

60 lines
1.4 KiB

  1. package auth
  2. import (
  3. "context"
  4. "log"
  5. "reflect"
  6. "git.aiterp.net/rpdata/api/models"
  7. )
  8. // CheckPermission does some magic.
  9. func CheckPermission(ctx context.Context, op string, obj interface{}) error {
  10. token := TokenFromContext(ctx)
  11. if token == nil {
  12. return ErrUnauthenticated
  13. }
  14. if v := reflect.ValueOf(obj); v.Kind() == reflect.Struct {
  15. ptr := reflect.PtrTo(v.Type())
  16. ptrValue := reflect.New(ptr.Elem())
  17. ptrValue.Elem().Set(v)
  18. obj = ptrValue.Interface()
  19. }
  20. var authorized = false
  21. switch v := obj.(type) {
  22. case *models.Channel:
  23. authorized = token.Permitted("channel." + op)
  24. case *models.Character:
  25. authorized = token.PermittedUser(v.Author, "member", "character."+op)
  26. case *models.Chapter:
  27. authorized = token.PermittedUser(v.Author, "member", "chapter."+op)
  28. case *models.Comment:
  29. if op == "add" && v.Author != token.UserID {
  30. return ErrInvalidOperation
  31. }
  32. authorized = token.PermittedUser(v.Author, "member", "comment."+op)
  33. case *models.File:
  34. authorized = token.PermittedUser(v.Author, "member", "file."+op)
  35. case *models.Log:
  36. authorized = token.Permitted("log." + op)
  37. case *models.Post:
  38. authorized = token.Permitted("post." + op)
  39. case *models.Story:
  40. authorized = token.PermittedUser(v.Author, "member", "story."+op)
  41. case *models.User:
  42. authorized = token.Permitted("user." + op)
  43. default:
  44. log.Panicf("Invalid model %T: %#+v", v, v)
  45. }
  46. if !authorized {
  47. return ErrUnauthorized
  48. }
  49. return nil
  50. }