request.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import abc
  2. from dataclasses import dataclass
  3. from dataclasses_json import dataclass_json
  4. from datetime import datetime
  5. from typing import List, Mapping, Optional, TypeVar, Type
  6. import lc.config as c
  7. import lc.error as e
  8. T = TypeVar("T")
  9. class Request(metaclass=abc.ABCMeta):
  10. @classmethod
  11. @abc.abstractmethod
  12. def from_form(cls: Type[T], form: Mapping[str, str]) -> T:
  13. pass
  14. # technically this gets added by dataclass_json, but mypy isn't
  15. # aware of it, so it's going to get declared here as though it
  16. # weren't abstract and then dataclass_json will add it
  17. @classmethod
  18. def from_json(cls: Type[T], json: bytes) -> T:
  19. pass
  20. @dataclass_json
  21. @dataclass
  22. class User(Request):
  23. name: str
  24. password: str
  25. @classmethod
  26. def from_form(cls, form: Mapping[str, str]):
  27. return cls(
  28. name=form["username"],
  29. password=form["password"],
  30. )
  31. def to_token(self) -> str:
  32. return c.app.serialize_token({"name": self.name})
  33. @dataclass_json
  34. @dataclass
  35. class NewUser(Request):
  36. name: str
  37. n1: str
  38. n2: str
  39. @classmethod
  40. def from_form(cls, form: Mapping[str, str]):
  41. return cls(
  42. name=form["username"],
  43. n1=form["n1"],
  44. n2=form["n2"],
  45. )
  46. def to_user_request(self) -> User:
  47. if self.n1 != self.n2:
  48. raise e.MismatchedPassword()
  49. return User(name=self.name, password=self.n1)
  50. @dataclass_json
  51. @dataclass
  52. class PasswordChange(Request):
  53. n1: str
  54. n2: str
  55. old: str
  56. @classmethod
  57. def from_form(cls, form: Mapping[str, str]):
  58. return cls(
  59. old=form["old"],
  60. n1=form["n1"],
  61. n2=form["n2"],
  62. )
  63. def require_match(self):
  64. if self.n1 != self.n2:
  65. raise e.MismatchedPassword()
  66. @dataclass_json
  67. @dataclass
  68. class Link(Request):
  69. url: str
  70. name: str
  71. description: str
  72. private: bool
  73. tags: List[str]
  74. created: Optional[datetime] = None
  75. @classmethod
  76. def from_form(cls, form: Mapping[str, str]):
  77. return cls(
  78. url=form["url"],
  79. name=form["name"],
  80. description=form["description"],
  81. private="private" in form,
  82. tags=form["tags"].split(),
  83. )