context_user.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. package context
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "strings"
  6. "time"
  7. "unicode"
  8. )
  9. // ErrNotSupported is fired when a specific method is not implemented
  10. // or not supported entirely.
  11. // Can be used by User implementations when
  12. // an authentication system does not implement a specific, but required,
  13. // method of the User interface.
  14. var ErrNotSupported = errors.New("not supported")
  15. // User is a generic view of an authorized client.
  16. // See `Context.User` and `SetUser` methods for more.
  17. //
  18. // The informational methods starts with a "Get" prefix
  19. // in order to allow the implementation to contain exported
  20. // fields such as `Username` so they can be JSON encoded when necessary.
  21. //
  22. // The caller is free to cast this with the implementation directly
  23. // when special features are offered by the authorization system.
  24. //
  25. // To make optional some of the fields you can just embed the User interface
  26. // and implement whatever methods you want to support.
  27. //
  28. // There are three builtin implementations of the User interface:
  29. // - SimpleUser
  30. // - UserMap (a wrapper by SetUser)
  31. // - UserPartial (a wrapper by SetUser)
  32. type User interface {
  33. // GetRaw should return the raw instance of the user, if supported.
  34. GetRaw() (interface{}, error)
  35. // GetAuthorization should return the authorization method,
  36. // e.g. Basic Authentication.
  37. GetAuthorization() (string, error)
  38. // GetAuthorizedAt should return the exact time the
  39. // client has been authorized for the "first" time.
  40. GetAuthorizedAt() (time.Time, error)
  41. // GetID should return the ID of the User.
  42. GetID() (string, error)
  43. // GetUsername should return the name of the User.
  44. GetUsername() (string, error)
  45. // GetPassword should return the encoded or raw password
  46. // (depends on the implementation) of the User.
  47. GetPassword() (string, error)
  48. // GetEmail should return the e-mail of the User.
  49. GetEmail() (string, error)
  50. // GetRoles should optionally return the specific user's roles.
  51. // Returns `ErrNotSupported` if this method is not
  52. // implemented by the User implementation.
  53. GetRoles() ([]string, error)
  54. // GetToken should optionally return a token used
  55. // to authorize this User.
  56. GetToken() ([]byte, error)
  57. // GetField should optionally return a dynamic field
  58. // based on its key. Useful for custom user fields.
  59. // Keep in mind that these fields are encoded as a separate JSON key.
  60. GetField(key string) (interface{}, error)
  61. } /* Notes:
  62. We could use a structure of User wrapper and separate interfaces for each of the methods
  63. so they return ErrNotSupported if the implementation is missing it, so the `Features`
  64. field and HasUserFeature can be omitted and
  65. add a Raw() interface{} to return the underline User implementation too.
  66. The advandages of the above idea is that we don't have to add new methods
  67. for each of the builtin features and we can keep the (assumed) struct small.
  68. But we dont as it has many disadvantages, unless is requested.
  69. ^ UPDATE: this is done through UserPartial.
  70. The disadvantage of the current implementation is that the developer MUST
  71. complete the whole interface in order to be a valid User and if we add
  72. new methods in the future their implementation will break
  73. (unless they have a static interface implementation check as we have on SimpleUser).
  74. We kind of by-pass this disadvantage by providing a SimpleUser which can be embedded (as pointer)
  75. to the end-developer's custom implementations.
  76. */
  77. // SimpleUser is a simple implementation of the User interface.
  78. type SimpleUser struct {
  79. Authorization string `json:"authorization,omitempty" db:"authorization"`
  80. AuthorizedAt time.Time `json:"authorized_at,omitempty" db:"authorized_at"`
  81. ID string `json:"id,omitempty" db:"id"`
  82. Username string `json:"username,omitempty" db:"username"`
  83. Password string `json:"password,omitempty" db:"password"`
  84. Email string `json:"email,omitempty" db:"email"`
  85. Roles []string `json:"roles,omitempty" db:"roles"`
  86. Token json.RawMessage `json:"token,omitempty" db:"token"`
  87. Fields Map `json:"fields,omitempty" db:"fields"`
  88. }
  89. var _ User = (*SimpleUser)(nil)
  90. // GetRaw returns itself.
  91. func (u *SimpleUser) GetRaw() (interface{}, error) {
  92. return u, nil
  93. }
  94. // GetAuthorization returns the authorization method,
  95. // e.g. Basic Authentication.
  96. func (u *SimpleUser) GetAuthorization() (string, error) {
  97. return u.Authorization, nil
  98. }
  99. // GetAuthorizedAt returns the exact time the
  100. // client has been authorized for the "first" time.
  101. func (u *SimpleUser) GetAuthorizedAt() (time.Time, error) {
  102. return u.AuthorizedAt, nil
  103. }
  104. // GetID returns the ID of the User.
  105. func (u *SimpleUser) GetID() (string, error) {
  106. return u.ID, nil
  107. }
  108. // GetUsername returns the name of the User.
  109. func (u *SimpleUser) GetUsername() (string, error) {
  110. return u.Username, nil
  111. }
  112. // GetPassword returns the raw password of the User.
  113. func (u *SimpleUser) GetPassword() (string, error) {
  114. return u.Password, nil
  115. }
  116. // GetEmail returns the e-mail of (string,error) User.
  117. func (u *SimpleUser) GetEmail() (string, error) {
  118. return u.Email, nil
  119. }
  120. // GetRoles returns the specific user's roles.
  121. // Returns with `ErrNotSupported` if the Roles field is not initialized.
  122. func (u *SimpleUser) GetRoles() ([]string, error) {
  123. if u.Roles == nil {
  124. return nil, ErrNotSupported
  125. }
  126. return u.Roles, nil
  127. }
  128. // GetToken returns the token associated with this User.
  129. // It may return empty if the User is not featured with a Token.
  130. //
  131. // The implementation can change that behavior.
  132. // Returns with `ErrNotSupported` if the Token field is empty.
  133. func (u *SimpleUser) GetToken() ([]byte, error) {
  134. if len(u.Token) == 0 {
  135. return nil, ErrNotSupported
  136. }
  137. return u.Token, nil
  138. }
  139. // GetField optionally returns a dynamic field from the `Fields` field
  140. // based on its key.
  141. func (u *SimpleUser) GetField(key string) (interface{}, error) {
  142. if u.Fields == nil {
  143. return nil, ErrNotSupported
  144. }
  145. return u.Fields[key], nil
  146. }
  147. // UserMap can be used to convert a common map[string]interface{} to a User.
  148. // Usage:
  149. //
  150. // user := map[string]interface{}{
  151. // "username": "kataras",
  152. // "age" : 27,
  153. // }
  154. //
  155. // ctx.SetUser(user)
  156. // OR
  157. // user := UserStruct{....}
  158. // ctx.SetUser(user)
  159. // [...]
  160. // username, err := ctx.User().GetUsername()
  161. // field,err := ctx.User().GetField("age")
  162. // age := field.(int)
  163. // OR cast it:
  164. // user := ctx.User().(UserMap)
  165. // username := user["username"].(string)
  166. // age := user["age"].(int)
  167. type UserMap Map
  168. var _ User = UserMap{}
  169. // GetRaw returns the underline map.
  170. func (u UserMap) GetRaw() (interface{}, error) {
  171. return Map(u), nil
  172. }
  173. // GetAuthorization returns the authorization or Authorization value of the map.
  174. func (u UserMap) GetAuthorization() (string, error) {
  175. return u.str("authorization")
  176. }
  177. // GetAuthorizedAt returns the authorized_at or Authorized_At value of the map.
  178. func (u UserMap) GetAuthorizedAt() (time.Time, error) {
  179. return u.time("authorized_at")
  180. }
  181. // GetID returns the id or Id or ID value of the map.
  182. func (u UserMap) GetID() (string, error) {
  183. return u.str("id")
  184. }
  185. // GetUsername returns the username or Username value of the map.
  186. func (u UserMap) GetUsername() (string, error) {
  187. return u.str("username")
  188. }
  189. // GetPassword returns the password or Password value of the map.
  190. func (u UserMap) GetPassword() (string, error) {
  191. return u.str("password")
  192. }
  193. // GetEmail returns the email or Email value of the map.
  194. func (u UserMap) GetEmail() (string, error) {
  195. return u.str("email")
  196. }
  197. // GetRoles returns the roles or Roles value of the map.
  198. func (u UserMap) GetRoles() ([]string, error) {
  199. return u.strSlice("roles")
  200. }
  201. // GetToken returns the roles or Roles value of the map.
  202. func (u UserMap) GetToken() ([]byte, error) {
  203. return u.bytes("token")
  204. }
  205. // GetField returns the raw map's value based on its "key".
  206. // It's not kind of useful here as you can just use the map.
  207. func (u UserMap) GetField(key string) (interface{}, error) {
  208. return u[key], nil
  209. }
  210. func (u UserMap) val(key string) interface{} {
  211. isTitle := unicode.IsTitle(rune(key[0])) // if starts with uppercase.
  212. if isTitle {
  213. key = strings.ToLower(key)
  214. }
  215. return u[key]
  216. }
  217. func (u UserMap) bytes(key string) ([]byte, error) {
  218. if v := u.val(key); v != nil {
  219. switch s := v.(type) {
  220. case []byte:
  221. return s, nil
  222. case string:
  223. return []byte(s), nil
  224. }
  225. }
  226. return nil, ErrNotSupported
  227. }
  228. func (u UserMap) str(key string) (string, error) {
  229. if v := u.val(key); v != nil {
  230. if s, ok := v.(string); ok {
  231. return s, nil
  232. }
  233. // exists or not we don't care, if it's invalid type we don't fill it.
  234. }
  235. return "", ErrNotSupported
  236. }
  237. func (u UserMap) strSlice(key string) ([]string, error) {
  238. if v := u.val(key); v != nil {
  239. if s, ok := v.([]string); ok {
  240. return s, nil
  241. }
  242. }
  243. return nil, ErrNotSupported
  244. }
  245. func (u UserMap) time(key string) (time.Time, error) {
  246. if v := u.val(key); v != nil {
  247. if t, ok := v.(time.Time); ok {
  248. return t, nil
  249. }
  250. }
  251. return time.Time{}, ErrNotSupported
  252. }
  253. type (
  254. userGetAuthorization interface {
  255. GetAuthorization() string
  256. }
  257. userGetAuthorizedAt interface {
  258. GetAuthorizedAt() time.Time
  259. }
  260. userGetID interface {
  261. GetID() string
  262. }
  263. // UserGetUsername interface which
  264. // requires a single method to complete
  265. // a User on Context.SetUser.
  266. UserGetUsername interface {
  267. GetUsername() string
  268. }
  269. // UserGetPassword interface which
  270. // requires a single method to complete
  271. // a User on Context.SetUser.
  272. UserGetPassword interface {
  273. GetPassword() string
  274. }
  275. userGetEmail interface {
  276. GetEmail() string
  277. }
  278. userGetRoles interface {
  279. GetRoles() []string
  280. }
  281. userGetToken interface {
  282. GetToken() []byte
  283. }
  284. userGetField interface {
  285. GetField(string) interface{}
  286. }
  287. // UserPartial is a User.
  288. // It's a helper which wraps a struct value that
  289. // may or may not complete the whole User interface.
  290. // See Context.SetUser.
  291. UserPartial struct {
  292. Raw interface{} `json:"raw"`
  293. userGetAuthorization `json:",omitempty"`
  294. userGetAuthorizedAt `json:",omitempty"`
  295. userGetID `json:",omitempty"`
  296. UserGetUsername `json:",omitempty"`
  297. UserGetPassword `json:",omitempty"`
  298. userGetEmail `json:",omitempty"`
  299. userGetRoles `json:",omitempty"`
  300. userGetToken `json:",omitempty"`
  301. userGetField `json:",omitempty"`
  302. }
  303. )
  304. var _ User = (*UserPartial)(nil)
  305. func newUserPartial(i interface{}) *UserPartial {
  306. if i == nil {
  307. return nil
  308. }
  309. p := &UserPartial{Raw: i}
  310. if u, ok := i.(userGetAuthorization); ok {
  311. p.userGetAuthorization = u
  312. }
  313. if u, ok := i.(userGetAuthorizedAt); ok {
  314. p.userGetAuthorizedAt = u
  315. }
  316. if u, ok := i.(userGetID); ok {
  317. p.userGetID = u
  318. }
  319. if u, ok := i.(UserGetUsername); ok {
  320. p.UserGetUsername = u
  321. }
  322. if u, ok := i.(UserGetPassword); ok {
  323. p.UserGetPassword = u
  324. }
  325. if u, ok := i.(userGetEmail); ok {
  326. p.userGetEmail = u
  327. }
  328. if u, ok := i.(userGetRoles); ok {
  329. p.userGetRoles = u
  330. }
  331. if u, ok := i.(userGetToken); ok {
  332. p.userGetToken = u
  333. }
  334. if u, ok := i.(userGetField); ok {
  335. p.userGetField = u
  336. }
  337. // if !containsAtLeastOneMethod {
  338. // return nil
  339. // }
  340. return p
  341. }
  342. // GetRaw returns the original raw instance of the user.
  343. func (u *UserPartial) GetRaw() (interface{}, error) {
  344. if u == nil {
  345. return nil, ErrNotSupported
  346. }
  347. return u.Raw, nil
  348. }
  349. // GetAuthorization should return the authorization method,
  350. // e.g. Basic Authentication.
  351. func (u *UserPartial) GetAuthorization() (string, error) {
  352. if v := u.userGetAuthorization; v != nil {
  353. return v.GetAuthorization(), nil
  354. }
  355. return "", ErrNotSupported
  356. }
  357. // GetAuthorizedAt should return the exact time the
  358. // client has been authorized for the "first" time.
  359. func (u *UserPartial) GetAuthorizedAt() (time.Time, error) {
  360. if v := u.userGetAuthorizedAt; v != nil {
  361. return v.GetAuthorizedAt(), nil
  362. }
  363. return time.Time{}, ErrNotSupported
  364. }
  365. // GetID should return the ID of the User.
  366. func (u *UserPartial) GetID() (string, error) {
  367. if v := u.userGetID; v != nil {
  368. return v.GetID(), nil
  369. }
  370. return "", ErrNotSupported
  371. }
  372. // GetUsername should return the name of the User.
  373. func (u *UserPartial) GetUsername() (string, error) {
  374. if v := u.UserGetUsername; v != nil {
  375. return v.GetUsername(), nil
  376. }
  377. return "", ErrNotSupported
  378. }
  379. // GetPassword should return the encoded or raw password
  380. // (depends on the implementation) of the User.
  381. func (u *UserPartial) GetPassword() (string, error) {
  382. if v := u.UserGetPassword; v != nil {
  383. return v.GetPassword(), nil
  384. }
  385. return "", ErrNotSupported
  386. }
  387. // GetEmail should return the e-mail of the User.
  388. func (u *UserPartial) GetEmail() (string, error) {
  389. if v := u.userGetEmail; v != nil {
  390. return v.GetEmail(), nil
  391. }
  392. return "", ErrNotSupported
  393. }
  394. // GetRoles should optionally return the specific user's roles.
  395. // Returns `ErrNotSupported` if this method is not
  396. // implemented by the User implementation.
  397. func (u *UserPartial) GetRoles() ([]string, error) {
  398. if v := u.userGetRoles; v != nil {
  399. return v.GetRoles(), nil
  400. }
  401. return nil, ErrNotSupported
  402. }
  403. // GetToken should optionally return a token used
  404. // to authorize this User.
  405. func (u *UserPartial) GetToken() ([]byte, error) {
  406. if v := u.userGetToken; v != nil {
  407. return v.GetToken(), nil
  408. }
  409. return nil, ErrNotSupported
  410. }
  411. // GetField should optionally return a dynamic field
  412. // based on its key. Useful for custom user fields.
  413. // Keep in mind that these fields are encoded as a separate JSON key.
  414. func (u *UserPartial) GetField(key string) (interface{}, error) {
  415. if v := u.userGetField; v != nil {
  416. return v.GetField(key), nil
  417. }
  418. return nil, ErrNotSupported
  419. }