PageRenderTime 62ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/api/contacts/view.go

https://github.com/pomack/dsocial.go
Go | 391 lines | 225 code | 51 blank | 115 comment | 64 complexity | 1dc75a7cce1f3dcfa321efd56cabd533 MD5 | raw file
  1. package contacts
  2. import (
  3. "github.com/pomack/dsocial.go/api/apiutil"
  4. acct "github.com/pomack/dsocial.go/backend/accounts"
  5. "github.com/pomack/dsocial.go/backend/authentication"
  6. bc "github.com/pomack/dsocial.go/backend/contacts"
  7. dm "github.com/pomack/dsocial.go/models/dsocial"
  8. "github.com/pomack/jsonhelper.go/jsonhelper"
  9. wm "github.com/pomack/webmachine.go/webmachine"
  10. "io"
  11. "net/http"
  12. "net/url"
  13. "time"
  14. )
  15. type ViewContactRequestHandler struct {
  16. wm.DefaultRequestHandler
  17. ds acct.DataStore
  18. authDS authentication.DataStore
  19. contactsDS bc.DataStoreService
  20. }
  21. type ViewContactContext interface {
  22. AuthUser() *dm.User
  23. SetAuthUser(user *dm.User)
  24. User() *dm.User
  25. SetUser(user *dm.User)
  26. ContactId() string
  27. SetContactId(contactId string)
  28. Contact() *dm.Contact
  29. SetContact(contact *dm.Contact)
  30. Result() jsonhelper.JSONObject
  31. SetResult(result jsonhelper.JSONObject)
  32. LastModified() time.Time
  33. SetLastModified(lastModified time.Time)
  34. SetETag(etag string)
  35. ETag() string
  36. }
  37. type viewContactContext struct {
  38. authUser *dm.User
  39. user *dm.User
  40. contact *dm.Contact
  41. contactId string
  42. result jsonhelper.JSONObject
  43. lastModified time.Time
  44. etag string
  45. }
  46. func NewViewContactContext() ViewContactContext {
  47. return new(viewContactContext)
  48. }
  49. func (p *viewContactContext) AuthUser() *dm.User {
  50. return p.authUser
  51. }
  52. func (p *viewContactContext) SetAuthUser(user *dm.User) {
  53. p.authUser = user
  54. }
  55. func (p *viewContactContext) User() *dm.User {
  56. return p.user
  57. }
  58. func (p *viewContactContext) SetUser(user *dm.User) {
  59. p.user = user
  60. }
  61. func (p *viewContactContext) Contact() *dm.Contact {
  62. return p.contact
  63. }
  64. func (p *viewContactContext) SetContact(contact *dm.Contact) {
  65. p.contact = contact
  66. }
  67. func (p *viewContactContext) ContactId() string {
  68. return p.contactId
  69. }
  70. func (p *viewContactContext) SetContactId(contactId string) {
  71. p.contactId = contactId
  72. }
  73. func (p *viewContactContext) Result() jsonhelper.JSONObject {
  74. return p.result
  75. }
  76. func (p *viewContactContext) SetResult(result jsonhelper.JSONObject) {
  77. p.result = result
  78. }
  79. func (p *viewContactContext) LastModified() time.Time {
  80. return p.lastModified
  81. }
  82. func (p *viewContactContext) SetLastModified(lastModified time.Time) {
  83. p.lastModified = lastModified
  84. }
  85. func (p *viewContactContext) ETag() string {
  86. return p.etag
  87. }
  88. func (p *viewContactContext) SetETag(etag string) {
  89. p.etag = etag
  90. }
  91. func NewViewContactRequestHandler(ds acct.DataStore, authDS authentication.DataStore, contactsDS bc.DataStoreService) *ViewContactRequestHandler {
  92. return &ViewContactRequestHandler{ds: ds, authDS: authDS, contactsDS: contactsDS}
  93. }
  94. func (p *ViewContactRequestHandler) GenerateContext(req wm.Request, cxt wm.Context) ViewContactContext {
  95. if vcc, ok := cxt.(ViewContactContext); ok {
  96. return vcc
  97. }
  98. return NewViewContactContext()
  99. }
  100. func (p *ViewContactRequestHandler) HandlerFor(req wm.Request, writer wm.ResponseWriter) wm.RequestHandler {
  101. // /api/v1/json/u/<uid>/contacts/list
  102. // /u/<uid>/contacts/list
  103. path := req.URLParts()
  104. pathLen := len(path)
  105. if path[pathLen-1] == "" {
  106. // ignore trailing slash
  107. pathLen = pathLen - 1
  108. }
  109. if pathLen == 9 {
  110. if path[0] == "" && path[1] == "api" && path[2] == "v1" && path[3] == "json" && path[4] == "u" && path[6] == "contacts" && path[7] == "view" {
  111. return p
  112. }
  113. }
  114. if pathLen == 6 {
  115. if path[0] == "" && path[1] == "u" && path[3] == "contacts" && path[4] == "view" {
  116. return p
  117. }
  118. }
  119. return nil
  120. }
  121. func (p *ViewContactRequestHandler) StartRequest(req wm.Request, cxt wm.Context) (wm.Request, wm.Context) {
  122. spac := p.GenerateContext(req, cxt)
  123. return req, spac
  124. }
  125. /*
  126. func (p *UpdateAccountRequestHandler) ServiceAvailable(req wm.Request, cxt wm.Context) (bool, wm.Request, wm.Context, int, os.Error) {
  127. return true, req, cxt, 0, nil
  128. }
  129. */
  130. func (p *ViewContactRequestHandler) ResourceExists(req wm.Request, cxt wm.Context) (bool, wm.Request, wm.Context, int, error) {
  131. vcc := cxt.(ViewContactContext)
  132. path := req.URLParts()
  133. pathLen := len(path)
  134. if path[pathLen-1] == "" {
  135. // ignore trailing slash
  136. pathLen = pathLen - 1
  137. }
  138. contactId := ""
  139. if pathLen == 9 {
  140. contactId = path[8]
  141. } else if pathLen == 6 {
  142. contactId = path[5]
  143. }
  144. vcc.SetContactId(contactId)
  145. if contactId == "" || vcc.User() == nil || vcc.User().Id == "" {
  146. return false, req, cxt, 0, nil
  147. }
  148. contact, _, err := p.contactsDS.RetrieveDsocialContact(vcc.User().Id, contactId)
  149. vcc.SetContact(contact)
  150. if contact != nil {
  151. vcc.SetETag(contact.Etag)
  152. if contact.ModifiedAt > 0 {
  153. vcc.SetLastModified(time.Unix(contact.ModifiedAt, 0).UTC())
  154. }
  155. } else {
  156. vcc.SetETag("")
  157. vcc.SetLastModified(time.Time{})
  158. }
  159. httpStatus := 0
  160. if err != nil {
  161. httpStatus = http.StatusInternalServerError
  162. }
  163. return contact != nil, req, cxt, httpStatus, err
  164. }
  165. func (p *ViewContactRequestHandler) AllowedMethods(req wm.Request, cxt wm.Context) ([]string, wm.Request, wm.Context, int, error) {
  166. return []string{wm.GET, wm.HEAD}, req, cxt, 0, nil
  167. }
  168. func (p *ViewContactRequestHandler) IsAuthorized(req wm.Request, cxt wm.Context) (bool, string, wm.Request, wm.Context, int, error) {
  169. vcc := cxt.(ViewContactContext)
  170. hasSignature, authUserId, _, err := apiutil.CheckSignature(p.authDS, req.UnderlyingRequest())
  171. if !hasSignature || err != nil {
  172. return hasSignature, "dsocial", req, cxt, http.StatusUnauthorized, err
  173. }
  174. if authUserId != "" {
  175. authUser, _ := p.ds.RetrieveUserAccountById(authUserId)
  176. vcc.SetAuthUser(authUser)
  177. }
  178. userId := apiutil.UserIdFromRequestUrl(req)
  179. if userId != "" {
  180. user, _ := p.ds.RetrieveUserAccountById(userId)
  181. vcc.SetUser(user)
  182. }
  183. return true, "", req, cxt, 0, nil
  184. }
  185. func (p *ViewContactRequestHandler) Forbidden(req wm.Request, cxt wm.Context) (bool, wm.Request, wm.Context, int, error) {
  186. vcc := cxt.(ViewContactContext)
  187. if vcc.AuthUser() != nil && vcc.AuthUser().Accessible() && vcc.User() != nil && vcc.User().Accessible() && vcc.AuthUser().Id == vcc.User().Id {
  188. return false, req, cxt, 0, nil
  189. }
  190. // Cannot find user with specified id
  191. return true, req, cxt, 0, nil
  192. }
  193. /*
  194. func (p *ViewContactRequestHandler) AllowMissingPost(req wm.Request, cxt wm.Context) (bool, wm.Request, wm.Context, int, os.Error) {
  195. return false, req, cxt, 0, nil
  196. }
  197. */
  198. /*
  199. func (p *ViewContactRequestHandler) MalformedRequest(req wm.Request, cxt wm.Context) (bool, wm.Request, wm.Context, int, os.Error) {
  200. return false, req, cxt, 0, nil
  201. }
  202. */
  203. /*
  204. func (p *ViewContactRequestHandler) URITooLong(req wm.Request, cxt wm.Context) (bool, wm.Request, wm.Context, int, os.Error) {
  205. return false, req, cxt, 0, nil
  206. }
  207. */
  208. /*
  209. func (p *ViewContactRequestHandler) DeleteResource(req wm.Request, cxt wm.Context) (bool, wm.Request, wm.Context, int, os.Error) {
  210. return false, req, cxt, http.StatusInternalServerError, nil
  211. }
  212. */
  213. /*
  214. func (p *ViewContactRequestHandler) DeleteCompleted(req wm.Request, cxt wm.Context) (bool, wm.Request, wm.Context, int, os.Error) {
  215. return true, req, cxt, 0, nil
  216. }
  217. */
  218. /*
  219. func (p *ViewContactRequestHandler) PostIsCreate(req wm.Request, cxt wm.Context) (bool, wm.Request, wm.Context, int, os.Error) {
  220. return false, req, cxt, 0, nil
  221. }
  222. */
  223. /*
  224. func (p *ViewContactRequestHandler) CreatePath(req wm.Request, cxt wm.Context) (string, wm.Request, wm.Context, int, os.Error) {
  225. return "", req, cxt, 0, nil
  226. }
  227. */
  228. /*
  229. func (p *ViewContactRequestHandler) ProcessPost(req wm.Request, cxt wm.Context) (wm.Request, wm.Context, int, http.Header, io.WriterTo, os.Error) {
  230. mths, req, cxt, code, err := p.ContentTypesAccepted(req, cxt)
  231. if len(mths) > 0 {
  232. httpCode, httpHeaders, writerTo := mths[0].MediaTypeHandleInputFrom(req, cxt)
  233. return req, cxt, httpCode, httpHeaders, writerTo, nil
  234. }
  235. return req, cxt, code, nil, nil, err
  236. }
  237. */
  238. func (p *ViewContactRequestHandler) ContentTypesProvided(req wm.Request, cxt wm.Context) ([]wm.MediaTypeHandler, wm.Request, wm.Context, int, error) {
  239. genFunc := func() (jsonhelper.JSONObject, time.Time, string, int, http.Header) {
  240. vcc := cxt.(ViewContactContext)
  241. jsonObj := vcc.Result()
  242. headers := apiutil.AddNoCacheHeaders(nil)
  243. return jsonObj, vcc.LastModified(), vcc.ETag(), http.StatusOK, headers
  244. }
  245. return []wm.MediaTypeHandler{apiutil.NewJSONMediaTypeHandlerWithGenerator(genFunc, time.Time{}, "")}, req, cxt, 0, nil
  246. }
  247. func (p *ViewContactRequestHandler) ContentTypesAccepted(req wm.Request, cxt wm.Context) ([]wm.MediaTypeInputHandler, wm.Request, wm.Context, int, error) {
  248. arr := []wm.MediaTypeInputHandler{
  249. apiutil.NewJSONMediaTypeInputHandler("", "", p, req.Body()),
  250. apiutil.NewUrlEncodedMediaTypeInputHandler("", "", p),
  251. }
  252. return arr, req, cxt, 0, nil
  253. }
  254. /*
  255. func (p *ViewContactRequestHandler) IsLanguageAvailable(languages []string, req wm.Request, cxt wm.Context) (bool, wm.Request, wm.Context, int, os.Error) {
  256. }
  257. */
  258. /*
  259. func (p *ViewContactRequestHandler) CharsetsProvided(charsets []string, req wm.Request, cxt wm.Context) ([]CharsetHandler, wm.Request, wm.Context, int, os.Error) {
  260. }
  261. */
  262. /*
  263. func (p *ViewContactRequestHandler) EncodingsProvided(encodings []string, req wm.Request, cxt wm.Context) ([]EncodingHandler, wm.Request, wm.Context, int, os.Error) {
  264. }
  265. */
  266. /*
  267. func (p *ViewContactRequestHandler) Variances(req wm.Request, cxt wm.Context) ([]string, wm.Request, wm.Context, int, os.Error) {
  268. }
  269. */
  270. /*
  271. func (p *ViewContactRequestHandler) IsConflict(req wm.Request, cxt wm.Context) (bool, wm.Request, wm.Context, int, os.Error) {
  272. return false, req, cxt, 0, nil
  273. }
  274. */
  275. /*
  276. func (p *ViewContactRequestHandler) MultipleChoices(req wm.Request, cxt wm.Context) (bool, http.Header, wm.Request, wm.Context, int, os.Error) {
  277. return false, nil, req, cxt, 0, nil
  278. }
  279. */
  280. /*
  281. func (p *ViewContactRequestHandler) PreviouslyExisted(req wm.Request, cxt wm.Context) (bool, wm.Request, wm.Context, int, os.Error) {
  282. }
  283. */
  284. /*
  285. func (p *ViewContactRequestHandler) MovedPermanently(req wm.Request, cxt wm.Context) (string, wm.Request, wm.Context, int, os.Error) {
  286. }
  287. */
  288. /*
  289. func (p *ViewContactRequestHandler) MovedTemporarily(req wm.Request, cxt wm.Context) (string, wm.Request, wm.Context, int, os.Error) {
  290. }
  291. */
  292. func (p *ViewContactRequestHandler) LastModified(req wm.Request, cxt wm.Context) (time.Time, wm.Request, wm.Context, int, error) {
  293. vcc := cxt.(ViewContactContext)
  294. return vcc.LastModified(), req, cxt, 0, nil
  295. }
  296. /*
  297. func (p *ViewContactRequestHandler) Expires(req wm.Request, cxt wm.Context) (*time.Time, wm.Request, wm.Context, int, os.Error) {
  298. }
  299. */
  300. func (p *ViewContactRequestHandler) GenerateETag(req wm.Request, cxt wm.Context) (string, wm.Request, wm.Context, int, error) {
  301. vcc := cxt.(ViewContactContext)
  302. return vcc.ETag(), req, cxt, 0, nil
  303. }
  304. /*
  305. func (p *ViewContactRequestHandler) FinishRequest(req wm.Request, cxt wm.Context) (bool, wm.Request, wm.Context, int, os.Error) {
  306. return true, req, cxt, 0, nil
  307. }
  308. */
  309. /*
  310. func (p *ViewContactRequestHandler) ResponseIsRedirect(req wm.Request, cxt wm.Context) (bool, wm.Request, wm.Context, int, os.Error) {
  311. return false, req, cxt, 0, nil
  312. }
  313. */
  314. func (p *ViewContactRequestHandler) HasRespBody(req wm.Request, cxt wm.Context) bool {
  315. return true
  316. }
  317. func (p *ViewContactRequestHandler) HandleJSONObjectInputHandler(req wm.Request, cxt wm.Context, inputObj jsonhelper.JSONObject) (int, http.Header, io.WriterTo) {
  318. vcc := cxt.(ViewContactContext)
  319. return p.HandleInputHandlerAfterSetup(vcc)
  320. }
  321. func (p *ViewContactRequestHandler) HandleUrlEncodedInputHandler(req wm.Request, cxt wm.Context, inputObj url.Values) (int, http.Header, io.WriterTo) {
  322. vcc := cxt.(ViewContactContext)
  323. return p.HandleInputHandlerAfterSetup(vcc)
  324. }
  325. func (p *ViewContactRequestHandler) HandleInputHandlerAfterSetup(cxt ViewContactContext) (int, http.Header, io.WriterTo) {
  326. obj := jsonhelper.NewJSONObject()
  327. contactObj, _ := jsonhelper.Marshal(cxt.Contact())
  328. obj.Set("contact", contactObj)
  329. obj.Set("type", "contact")
  330. cxt.SetResult(obj)
  331. return 0, nil, nil
  332. }