builder.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. package perm
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/http"
  6. "reflect"
  7. "strings"
  8. "sync"
  9. "time"
  10. "github.com/iancoleman/strcase"
  11. "github.com/jinzhu/inflection"
  12. "github.com/ory/ladon"
  13. "github.com/ory/ladon/manager/memory"
  14. "github.com/sunfmin/reflectutils"
  15. "gorm.io/gorm"
  16. )
  17. const (
  18. Allowed = ladon.AllowAccess
  19. Denied = ladon.DenyAccess
  20. Anything = "*"
  21. Anybody = "*"
  22. Anonymous = "anonymous"
  23. )
  24. var PermissionDenied = errors.New("permission denied")
  25. type Context = ladon.Context
  26. type Conditions = ladon.Conditions
  27. type SubjectsFunc func(r *http.Request) []string
  28. type ContextFunc func(r *http.Request, objs []interface{}) Context
  29. type DBPolicy interface {
  30. LoadDBPolicies(db *gorm.DB, startFrom *time.Time) ([]*PolicyBuilder, []*PolicyBuilder)
  31. }
  32. type permRNer interface {
  33. PermissionRN() []string
  34. }
  35. func ToPermissionRN(v interface{}) []string {
  36. if pr, ok := v.(permRNer); ok {
  37. return pr.PermissionRN()
  38. }
  39. typeName := fmt.Sprint(reflect.TypeOf(v))
  40. ss := strings.Split(typeName, ".")
  41. typeName = ss[len(ss)-1]
  42. typeName = strings.NewReplacer("*", "", ".", "-").Replace(typeName)
  43. typeName = strcase.ToSnake(inflection.Plural(typeName))
  44. id, err := reflectutils.Get(v, "ID")
  45. if err == nil && len(fmt.Sprint(id)) > 0 && fmt.Sprint(id) != "0" {
  46. return []string{typeName, fmt.Sprint(id)}
  47. }
  48. return []string{typeName}
  49. }
  50. type Builder struct {
  51. m sync.Mutex
  52. policies []*PolicyBuilder
  53. ladon *ladon.Ladon
  54. subjectsFunc SubjectsFunc
  55. contextFunc ContextFunc
  56. dbPolicy *DBPolicyBuilder
  57. }
  58. func New() *Builder {
  59. return &Builder{
  60. ladon: &ladon.Ladon{
  61. Manager: memory.NewMemoryManager(),
  62. Matcher: &PathMatcher{},
  63. },
  64. }
  65. }
  66. func (b *Builder) Policies(ps ...*PolicyBuilder) (r *Builder) {
  67. b.DeletePolicies(b.policies...)
  68. b.policies = make([]*PolicyBuilder, 0)
  69. b.CreatePolicies(ps...)
  70. return b
  71. }
  72. func (b *Builder) createPolicy(p *PolicyBuilder) {
  73. p.setIDIfEmpty()
  74. err := b.ladon.Manager.Create(p.policy)
  75. if err != nil {
  76. panic(err)
  77. }
  78. b.policies = append(b.policies, p)
  79. }
  80. func (b *Builder) updatePolicy(p *PolicyBuilder) {
  81. i := b.findPolicyIndex(p.GetID())
  82. if i < 0 {
  83. return
  84. }
  85. err := b.ladon.Manager.Update(p.policy)
  86. if err != nil {
  87. panic(err)
  88. }
  89. b.policies[i] = p
  90. }
  91. func (b *Builder) findPolicyIndex(id string) int {
  92. for i, p := range b.policies {
  93. if p.GetID() == id {
  94. return i
  95. }
  96. }
  97. return -1
  98. }
  99. func (b *Builder) updateOrCreatePolicy(p *PolicyBuilder) {
  100. i := b.findPolicyIndex(p.GetID())
  101. if i < 0 {
  102. b.createPolicy(p)
  103. } else {
  104. b.updatePolicy(p)
  105. }
  106. }
  107. func (b *Builder) deletePolicy(p *PolicyBuilder) {
  108. for i, ep := range b.policies {
  109. if ep.GetID() == p.GetID() {
  110. err := b.ladon.Manager.Delete(p.GetID())
  111. if err != nil {
  112. panic(err)
  113. }
  114. b.policies = append(b.policies[:i], b.policies[i+1:]...)
  115. break
  116. }
  117. }
  118. }
  119. func (b *Builder) SubjectsFunc(v SubjectsFunc) (r *Builder) {
  120. b.subjectsFunc = v
  121. return b
  122. }
  123. func (b *Builder) GetSubjectsFunc() SubjectsFunc {
  124. return b.subjectsFunc
  125. }
  126. func (b *Builder) ContextFunc(v ContextFunc) (r *Builder) {
  127. b.contextFunc = v
  128. return b
  129. }
  130. func (b *Builder) GetContextFunc() ContextFunc {
  131. return b.contextFunc
  132. }
  133. func (b *Builder) DBPolicy(dpb *DBPolicyBuilder) (r *Builder) {
  134. b.dbPolicy = dpb
  135. go b.loopLoadDBPolicies(dpb.db, dpb.loadFrequency)
  136. return b
  137. }
  138. func (b *Builder) CreatePolicies(ps ...*PolicyBuilder) {
  139. b.m.Lock()
  140. defer b.m.Unlock()
  141. for _, p := range ps {
  142. b.createPolicy(p)
  143. }
  144. }
  145. func (b *Builder) UpdatePolicies(toUpdate ...*PolicyBuilder) {
  146. b.m.Lock()
  147. defer b.m.Unlock()
  148. for _, p := range toUpdate {
  149. b.updatePolicy(p)
  150. }
  151. }
  152. func (b *Builder) UpdateOrCreatePolicies(toUpdate ...*PolicyBuilder) {
  153. b.m.Lock()
  154. defer b.m.Unlock()
  155. for _, p := range toUpdate {
  156. b.updateOrCreatePolicy(p)
  157. }
  158. }
  159. func (b *Builder) DeletePolicies(toDelete ...*PolicyBuilder) {
  160. b.m.Lock()
  161. defer b.m.Unlock()
  162. for _, p := range toDelete {
  163. b.deletePolicy(p)
  164. }
  165. }
  166. func (b *Builder) LoadDBPoliciesToMemory(db *gorm.DB, startFrom *time.Time) {
  167. toUpdateOrCreate, toDelete := b.dbPolicy.model.LoadDBPolicies(db, startFrom)
  168. b.DeletePolicies(toDelete...)
  169. b.UpdateOrCreatePolicies(toUpdateOrCreate...)
  170. if Verbose {
  171. b.printPolices()
  172. }
  173. }
  174. func (b *Builder) loopLoadDBPolicies(db *gorm.DB, duration time.Duration) {
  175. now := time.Now()
  176. b.LoadDBPoliciesToMemory(db, nil)
  177. for next := range time.Tick(duration) {
  178. b.LoadDBPoliciesToMemory(db, &now)
  179. now = next
  180. }
  181. }
  182. func (b *Builder) printPolices() {
  183. allp, _ := b.ladon.Manager.GetAll(100, 0)
  184. fmt.Printf("all permission policies: \n")
  185. for _, p := range allp {
  186. fmt.Printf("%+v \n", p)
  187. }
  188. }