gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. // Copyright 2025 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package cmd
  4. import (
  5. "context"
  6. "testing"
  7. auth_model "code.gitea.io/gitea/models/auth"
  8. "code.gitea.io/gitea/services/auth/source/oauth2"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/urfave/cli/v3"
  11. )
  12. func TestAddOauth(t *testing.T) {
  13. testCases := []struct {
  14. name string
  15. args []string
  16. source *auth_model.Source
  17. errMsg string
  18. }{
  19. {
  20. name: "valid config",
  21. args: []string{
  22. "--name", "test",
  23. "--provider", "github",
  24. "--key", "some_key",
  25. "--secret", "some_secret",
  26. },
  27. source: &auth_model.Source{
  28. Type: auth_model.OAuth2,
  29. Name: "test",
  30. IsActive: true,
  31. Cfg: &oauth2.Source{
  32. Scopes: []string{},
  33. Provider: "github",
  34. ClientID: "some_key",
  35. ClientSecret: "some_secret",
  36. },
  37. TwoFactorPolicy: "",
  38. },
  39. },
  40. {
  41. name: "valid config with openid connect",
  42. args: []string{
  43. "--name", "test",
  44. "--provider", "openidConnect",
  45. "--key", "some_key",
  46. "--secret", "some_secret",
  47. "--auto-discover-url", "https://example.com",
  48. },
  49. source: &auth_model.Source{
  50. Type: auth_model.OAuth2,
  51. Name: "test",
  52. IsActive: true,
  53. Cfg: &oauth2.Source{
  54. Scopes: []string{},
  55. Provider: "openidConnect",
  56. ClientID: "some_key",
  57. ClientSecret: "some_secret",
  58. OpenIDConnectAutoDiscoveryURL: "https://example.com",
  59. },
  60. TwoFactorPolicy: "",
  61. },
  62. },
  63. {
  64. name: "valid config with options",
  65. args: []string{
  66. "--name", "test",
  67. "--provider", "gitlab",
  68. "--key", "some_key",
  69. "--secret", "some_secret",
  70. "--use-custom-urls", "true",
  71. "--custom-token-url", "https://example.com/token",
  72. "--custom-auth-url", "https://example.com/auth",
  73. "--custom-profile-url", "https://example.com/profile",
  74. "--custom-email-url", "https://example.com/email",
  75. "--custom-tenant-id", "some_tenant",
  76. "--icon-url", "https://example.com/icon",
  77. "--scopes", "scope1,scope2",
  78. "--skip-local-2fa", "true",
  79. "--required-claim-name", "claim_name",
  80. "--required-claim-value", "claim_value",
  81. "--group-claim-name", "group_name",
  82. "--admin-group", "admin",
  83. "--restricted-group", "restricted",
  84. "--group-team-map", `{"group1": [1,2]}`,
  85. "--group-team-map-removal=true",
  86. "--ssh-public-key-claim-name", "attr_ssh_pub_key",
  87. "--full-name-claim-name", "attr_full_name",
  88. },
  89. source: &auth_model.Source{
  90. Type: auth_model.OAuth2,
  91. Name: "test",
  92. IsActive: true,
  93. Cfg: &oauth2.Source{
  94. Provider: "gitlab",
  95. ClientID: "some_key",
  96. ClientSecret: "some_secret",
  97. CustomURLMapping: &oauth2.CustomURLMapping{
  98. TokenURL: "https://example.com/token",
  99. AuthURL: "https://example.com/auth",
  100. ProfileURL: "https://example.com/profile",
  101. EmailURL: "https://example.com/email",
  102. Tenant: "some_tenant",
  103. },
  104. IconURL: "https://example.com/icon",
  105. Scopes: []string{"scope1", "scope2"},
  106. RequiredClaimName: "claim_name",
  107. RequiredClaimValue: "claim_value",
  108. GroupClaimName: "group_name",
  109. AdminGroup: "admin",
  110. RestrictedGroup: "restricted",
  111. GroupTeamMap: `{"group1": [1,2]}`,
  112. GroupTeamMapRemoval: true,
  113. SSHPublicKeyClaimName: "attr_ssh_pub_key",
  114. FullNameClaimName: "attr_full_name",
  115. },
  116. TwoFactorPolicy: "skip",
  117. },
  118. },
  119. }
  120. for _, tc := range testCases {
  121. t.Run(tc.name, func(t *testing.T) {
  122. var createdSource *auth_model.Source
  123. a := &authService{
  124. initDB: func(ctx context.Context) error {
  125. return nil
  126. },
  127. createAuthSource: func(ctx context.Context, source *auth_model.Source) error {
  128. createdSource = source
  129. return nil
  130. },
  131. }
  132. app := &cli.Command{
  133. Flags: microcmdAuthAddOauth().Flags,
  134. Action: a.runAddOauth,
  135. }
  136. args := []string{"oauth-test"}
  137. args = append(args, tc.args...)
  138. err := app.Run(t.Context(), args)
  139. if tc.errMsg != "" {
  140. assert.EqualError(t, err, tc.errMsg)
  141. } else {
  142. assert.NoError(t, err)
  143. assert.Equal(t, tc.source, createdSource)
  144. }
  145. })
  146. }
  147. }
  148. func TestUpdateOauth(t *testing.T) {
  149. testCases := []struct {
  150. name string
  151. args []string
  152. id int64
  153. existingAuthSource *auth_model.Source
  154. authSource *auth_model.Source
  155. errMsg string
  156. }{
  157. {
  158. name: "missing id",
  159. args: []string{
  160. "--name", "test",
  161. },
  162. errMsg: "--id flag is missing",
  163. },
  164. {
  165. name: "valid config",
  166. id: 1,
  167. existingAuthSource: &auth_model.Source{
  168. ID: 1,
  169. Type: auth_model.OAuth2,
  170. Name: "old name",
  171. IsActive: true,
  172. Cfg: &oauth2.Source{
  173. Provider: "github",
  174. ClientID: "old_key",
  175. ClientSecret: "old_secret",
  176. },
  177. TwoFactorPolicy: "",
  178. },
  179. args: []string{
  180. "--id", "1",
  181. "--name", "test",
  182. "--provider", "gitlab",
  183. "--key", "new_key",
  184. "--secret", "new_secret",
  185. },
  186. authSource: &auth_model.Source{
  187. ID: 1,
  188. Type: auth_model.OAuth2,
  189. Name: "test",
  190. IsActive: true,
  191. Cfg: &oauth2.Source{
  192. Provider: "gitlab",
  193. ClientID: "new_key",
  194. ClientSecret: "new_secret",
  195. CustomURLMapping: &oauth2.CustomURLMapping{},
  196. },
  197. TwoFactorPolicy: "",
  198. },
  199. },
  200. {
  201. name: "valid config with options",
  202. id: 1,
  203. existingAuthSource: &auth_model.Source{
  204. ID: 1,
  205. Type: auth_model.OAuth2,
  206. Name: "old name",
  207. IsActive: true,
  208. Cfg: &oauth2.Source{
  209. Provider: "gitlab",
  210. ClientID: "old_key",
  211. ClientSecret: "old_secret",
  212. CustomURLMapping: &oauth2.CustomURLMapping{
  213. TokenURL: "https://old.example.com/token",
  214. AuthURL: "https://old.example.com/auth",
  215. ProfileURL: "https://old.example.com/profile",
  216. EmailURL: "https://old.example.com/email",
  217. Tenant: "old_tenant",
  218. },
  219. IconURL: "https://old.example.com/icon",
  220. Scopes: []string{"old_scope1", "old_scope2"},
  221. RequiredClaimName: "old_claim_name",
  222. RequiredClaimValue: "old_claim_value",
  223. GroupClaimName: "old_group_name",
  224. AdminGroup: "old_admin",
  225. RestrictedGroup: "old_restricted",
  226. GroupTeamMap: `{"old_group1": [1,2]}`,
  227. GroupTeamMapRemoval: true,
  228. SSHPublicKeyClaimName: "old_ssh_pub_key",
  229. FullNameClaimName: "old_full_name",
  230. },
  231. TwoFactorPolicy: "",
  232. },
  233. args: []string{
  234. "--id", "1",
  235. "--name", "test",
  236. "--provider", "github",
  237. "--key", "new_key",
  238. "--secret", "new_secret",
  239. "--use-custom-urls", "true",
  240. "--custom-token-url", "https://example.com/token",
  241. "--custom-auth-url", "https://example.com/auth",
  242. "--custom-profile-url", "https://example.com/profile",
  243. "--custom-email-url", "https://example.com/email",
  244. "--custom-tenant-id", "new_tenant",
  245. "--icon-url", "https://example.com/icon",
  246. "--scopes", "scope1,scope2",
  247. "--skip-local-2fa=true",
  248. "--required-claim-name", "claim_name",
  249. "--required-claim-value", "claim_value",
  250. "--group-claim-name", "group_name",
  251. "--admin-group", "admin",
  252. "--restricted-group", "restricted",
  253. "--group-team-map", `{"group1": [1,2]}`,
  254. "--group-team-map-removal=false",
  255. "--ssh-public-key-claim-name", "new_ssh_pub_key",
  256. "--full-name-claim-name", "new_full_name",
  257. },
  258. authSource: &auth_model.Source{
  259. ID: 1,
  260. Type: auth_model.OAuth2,
  261. Name: "test",
  262. IsActive: true,
  263. Cfg: &oauth2.Source{
  264. Provider: "github",
  265. ClientID: "new_key",
  266. ClientSecret: "new_secret",
  267. CustomURLMapping: &oauth2.CustomURLMapping{
  268. TokenURL: "https://example.com/token",
  269. AuthURL: "https://example.com/auth",
  270. ProfileURL: "https://example.com/profile",
  271. EmailURL: "https://example.com/email",
  272. Tenant: "new_tenant",
  273. },
  274. IconURL: "https://example.com/icon",
  275. Scopes: []string{"scope1", "scope2"},
  276. RequiredClaimName: "claim_name",
  277. RequiredClaimValue: "claim_value",
  278. GroupClaimName: "group_name",
  279. AdminGroup: "admin",
  280. RestrictedGroup: "restricted",
  281. GroupTeamMap: `{"group1": [1,2]}`,
  282. GroupTeamMapRemoval: false,
  283. SSHPublicKeyClaimName: "new_ssh_pub_key",
  284. FullNameClaimName: "new_full_name",
  285. },
  286. TwoFactorPolicy: "skip",
  287. },
  288. },
  289. }
  290. for _, tc := range testCases {
  291. t.Run(tc.name, func(t *testing.T) {
  292. a := &authService{
  293. initDB: func(ctx context.Context) error {
  294. return nil
  295. },
  296. getAuthSourceByID: func(ctx context.Context, id int64) (*auth_model.Source, error) {
  297. return &auth_model.Source{
  298. ID: 1,
  299. Type: auth_model.OAuth2,
  300. Name: "test",
  301. IsActive: true,
  302. Cfg: &oauth2.Source{
  303. CustomURLMapping: &oauth2.CustomURLMapping{},
  304. },
  305. TwoFactorPolicy: "skip",
  306. }, nil
  307. },
  308. updateAuthSource: func(ctx context.Context, source *auth_model.Source) error {
  309. assert.Equal(t, tc.authSource, source)
  310. return nil
  311. },
  312. }
  313. app := &cli.Command{
  314. Flags: microcmdAuthUpdateOauth().Flags,
  315. Action: a.runUpdateOauth,
  316. }
  317. args := []string{"oauth-test"}
  318. args = append(args, tc.args...)
  319. err := app.Run(t.Context(), args)
  320. if tc.errMsg != "" {
  321. assert.EqualError(t, err, tc.errMsg)
  322. } else {
  323. assert.NoError(t, err)
  324. }
  325. })
  326. }
  327. }