oauth.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package model
  2. import (
  3. "errors"
  4. "strconv"
  5. "strings"
  6. )
  7. const OIDC_DEFAULT_SCOPES = "openid,profile,email"
  8. const (
  9. // make sure the value shouldbe lowercase
  10. OauthTypeGithub string = "github"
  11. OauthTypeGoogle string = "google"
  12. OauthTypeOidc string = "oidc"
  13. OauthTypeWebauth string = "webauth"
  14. )
  15. // Validate the oauth type
  16. func ValidateOauthType(oauthType string) error {
  17. switch oauthType {
  18. case OauthTypeGithub, OauthTypeGoogle, OauthTypeOidc, OauthTypeWebauth:
  19. return nil
  20. default:
  21. return errors.New("invalid Oauth type")
  22. }
  23. }
  24. const (
  25. UserEndpointGithub string = "https://api.github.com/user"
  26. IssuerGoogle string = "https://accounts.google.com"
  27. )
  28. type Oauth struct {
  29. IdModel
  30. Op string `json:"op"`
  31. OauthType string `json:"oauth_type"`
  32. ClientId string `json:"client_id"`
  33. ClientSecret string `json:"client_secret"`
  34. RedirectUrl string `json:"redirect_url"`
  35. AutoRegister *bool `json:"auto_register"`
  36. Scopes string `json:"scopes"`
  37. Issuer string `json:"issuer"`
  38. TimeModel
  39. }
  40. // Helper function to format oauth info, it's used in the update and create method
  41. func (oa *Oauth) FormatOauthInfo() error {
  42. oauthType := strings.TrimSpace(oa.OauthType)
  43. err := ValidateOauthType(oa.OauthType)
  44. if err != nil {
  45. return err
  46. }
  47. switch oauthType {
  48. case OauthTypeGithub:
  49. oa.Op = OauthTypeGithub
  50. case OauthTypeGoogle:
  51. oa.Op = OauthTypeGoogle
  52. }
  53. // check if the op is empty, set the default value
  54. op := strings.TrimSpace(oa.Op)
  55. if op == "" && oauthType == OauthTypeOidc {
  56. oa.Op = OauthTypeOidc
  57. }
  58. // check the issuer, if the oauth type is google and the issuer is empty, set the issuer to the default value
  59. issuer := strings.TrimSpace(oa.Issuer)
  60. // If the oauth type is google and the issuer is empty, set the issuer to the default value
  61. if oauthType == OauthTypeGoogle && issuer == "" {
  62. oa.Issuer = IssuerGoogle
  63. }
  64. return nil
  65. }
  66. type OauthUser struct {
  67. OpenId string `json:"open_id" gorm:"not null;index"`
  68. Name string `json:"name"`
  69. Username string `json:"username"`
  70. Email string `json:"email"`
  71. VerifiedEmail bool `json:"verified_email,omitempty"`
  72. Picture string `json:"picture,omitempty"`
  73. }
  74. func (ou *OauthUser) ToUser(user *User, overideUsername bool) {
  75. if overideUsername {
  76. user.Username = ou.Username
  77. }
  78. user.Email = ou.Email
  79. user.Nickname = ou.Name
  80. user.Avatar = ou.Picture
  81. }
  82. type OauthUserBase struct {
  83. Name string `json:"name"`
  84. Email string `json:"email"`
  85. }
  86. type OidcUser struct {
  87. OauthUserBase
  88. Sub string `json:"sub"`
  89. VerifiedEmail bool `json:"email_verified"`
  90. PreferredUsername string `json:"preferred_username"`
  91. Picture string `json:"picture"`
  92. }
  93. func (ou *OidcUser) ToOauthUser() *OauthUser {
  94. var username string
  95. // 使用 PreferredUsername,如果不存在,降级到 Email 前缀
  96. if ou.PreferredUsername != "" {
  97. username = ou.PreferredUsername
  98. } else {
  99. username = strings.ToLower(ou.Email)
  100. }
  101. return &OauthUser{
  102. OpenId: ou.Sub,
  103. Name: ou.Name,
  104. Username: username,
  105. Email: ou.Email,
  106. VerifiedEmail: ou.VerifiedEmail,
  107. Picture: ou.Picture,
  108. }
  109. }
  110. type GithubUser struct {
  111. OauthUserBase
  112. Id int `json:"id"`
  113. Login string `json:"login"`
  114. AvatarUrl string `json:"avatar_url"`
  115. VerifiedEmail bool `json:"verified_email"`
  116. }
  117. func (gu *GithubUser) ToOauthUser() *OauthUser {
  118. username := strings.ToLower(gu.Login)
  119. return &OauthUser{
  120. OpenId: strconv.Itoa(gu.Id),
  121. Name: gu.Name,
  122. Username: username,
  123. Email: gu.Email,
  124. VerifiedEmail: gu.VerifiedEmail,
  125. Picture: gu.AvatarUrl,
  126. }
  127. }
  128. type OauthList struct {
  129. Oauths []*Oauth `json:"list"`
  130. Pagination
  131. }