prioritized user submitted OAuth2 createData.email
This commit is contained in:
		
							parent
							
								
									acd72101c6
								
							
						
					
					
						commit
						9856c59de0
					
				| 
						 | 
					@ -1,3 +1,8 @@
 | 
				
			||||||
 | 
					## v0.26.0 (WIP)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- ⚠️ Prioritized the user submitted non-empty `createData.email` (_it will be unverified_) when creating the PocketBase user during the first OAuth2 auth.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## v0.25.0
 | 
					## v0.25.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- ⚠️ Upgraded Google OAuth2 auth, token and userinfo endpoints to their latest versions.
 | 
					- ⚠️ Upgraded Google OAuth2 auth, token and userinfo endpoints to their latest versions.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -232,7 +232,11 @@ func oauth2Submit(e *core.RecordAuthWithOAuth2RequestEvent, optExternalAuth *cor
 | 
				
			||||||
				payload = map[string]any{}
 | 
									payload = map[string]any{}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// assign the OAuth2 user email only if the user hasn't submitted one
 | 
				
			||||||
 | 
								// (ignore empty/invalid values for consistency with the OAuth2->existing user update flow)
 | 
				
			||||||
 | 
								if v, _ := payload[core.FieldNameEmail].(string); v == "" {
 | 
				
			||||||
				payload[core.FieldNameEmail] = e.OAuth2User.Email
 | 
									payload[core.FieldNameEmail] = e.OAuth2User.Email
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// map known fields (unless the field was explicitly submitted as part of CreateData)
 | 
								// map known fields (unless the field was explicitly submitted as part of CreateData)
 | 
				
			||||||
			if _, ok := payload[e.Collection.OAuth2.MappedFields.Id]; !ok && e.Collection.OAuth2.MappedFields.Id != "" {
 | 
								if _, ok := payload[e.Collection.OAuth2.MappedFields.Id]; !ok && e.Collection.OAuth2.MappedFields.Id != "" {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -877,7 +877,7 @@ func TestRecordAuthWithOAuth2(t *testing.T) {
 | 
				
			||||||
				`"verified":{"code":"validation_values_mismatch"`,
 | 
									`"verified":{"code":"validation_values_mismatch"`,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			NotExpectedContent: []string{
 | 
								NotExpectedContent: []string{
 | 
				
			||||||
				`"email":`, // the value is always overwritten with the OAuth2 user email
 | 
									`"email":`, // ignored because the record validator never ran
 | 
				
			||||||
				`"rel":`,   // ignored because the record validator never ran
 | 
									`"rel":`,   // ignored because the record validator never ran
 | 
				
			||||||
				`"file":`,  // ignored because the record validator never ran
 | 
									`"file":`,  // ignored because the record validator never ran
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
| 
						 | 
					@ -930,12 +930,10 @@ func TestRecordAuthWithOAuth2(t *testing.T) {
 | 
				
			||||||
			ExpectedStatus: 400,
 | 
								ExpectedStatus: 400,
 | 
				
			||||||
			ExpectedContent: []string{
 | 
								ExpectedContent: []string{
 | 
				
			||||||
				`"data":{`,
 | 
									`"data":{`,
 | 
				
			||||||
 | 
									`"email":{"code":"validation_is_email"`,
 | 
				
			||||||
				`"rel":{"code":"validation_missing_rel_records"`,
 | 
									`"rel":{"code":"validation_missing_rel_records"`,
 | 
				
			||||||
				`"file":{"code":"validation_invalid_file"`,
 | 
									`"file":{"code":"validation_invalid_file"`,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			NotExpectedContent: []string{
 | 
					 | 
				
			||||||
				`"email":`, // the value is always overwritten with the OAuth2 user email
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			ExpectedEvents: map[string]int{
 | 
								ExpectedEvents: map[string]int{
 | 
				
			||||||
				"*":                             0,
 | 
									"*":                             0,
 | 
				
			||||||
				"OnRecordAuthWithOAuth2Request": 1,
 | 
									"OnRecordAuthWithOAuth2Request": 1,
 | 
				
			||||||
| 
						 | 
					@ -949,7 +947,7 @@ func TestRecordAuthWithOAuth2(t *testing.T) {
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			Name:   "creating user (valid create data)",
 | 
								Name:   "creating user (valid create data with empty submitted email)",
 | 
				
			||||||
			Method: http.MethodPost,
 | 
								Method: http.MethodPost,
 | 
				
			||||||
			URL:    "/api/collections/users/auth-with-oauth2",
 | 
								URL:    "/api/collections/users/auth-with-oauth2",
 | 
				
			||||||
			Body: strings.NewReader(`{
 | 
								Body: strings.NewReader(`{
 | 
				
			||||||
| 
						 | 
					@ -957,7 +955,7 @@ func TestRecordAuthWithOAuth2(t *testing.T) {
 | 
				
			||||||
				"code":"123",
 | 
									"code":"123",
 | 
				
			||||||
				"redirectURL": "https://example.com",
 | 
									"redirectURL": "https://example.com",
 | 
				
			||||||
				"createData": {
 | 
									"createData": {
 | 
				
			||||||
					"email": "invalid",
 | 
										"email": "",
 | 
				
			||||||
					"emailVisibility": true,
 | 
										"emailVisibility": true,
 | 
				
			||||||
					"password": "1234567890",
 | 
										"password": "1234567890",
 | 
				
			||||||
					"passwordConfirm": "1234567890",
 | 
										"passwordConfirm": "1234567890",
 | 
				
			||||||
| 
						 | 
					@ -1041,6 +1039,95 @@ func TestRecordAuthWithOAuth2(t *testing.T) {
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name:   "creating user (valid create data with non-empty valid submitted email)",
 | 
				
			||||||
 | 
								Method: http.MethodPost,
 | 
				
			||||||
 | 
								URL:    "/api/collections/users/auth-with-oauth2",
 | 
				
			||||||
 | 
								Body: strings.NewReader(`{
 | 
				
			||||||
 | 
									"provider": "test",
 | 
				
			||||||
 | 
									"code":"123",
 | 
				
			||||||
 | 
									"redirectURL": "https://example.com",
 | 
				
			||||||
 | 
									"createData": {
 | 
				
			||||||
 | 
										"email": "test_create@example.com",
 | 
				
			||||||
 | 
										"emailVisibility": true,
 | 
				
			||||||
 | 
										"password": "1234567890",
 | 
				
			||||||
 | 
										"passwordConfirm": "1234567890",
 | 
				
			||||||
 | 
										"name": "test_name",
 | 
				
			||||||
 | 
										"username": "test_username",
 | 
				
			||||||
 | 
										"rel": "0yxhwia2amd8gec"
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}`),
 | 
				
			||||||
 | 
								BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
 | 
				
			||||||
 | 
									usersCol, err := app.FindCollectionByNameOrId("users")
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										t.Fatal(err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// register the test provider
 | 
				
			||||||
 | 
									auth.Providers["test"] = func() auth.Provider {
 | 
				
			||||||
 | 
										return &oauth2MockProvider{
 | 
				
			||||||
 | 
											AuthUser: &auth.AuthUser{
 | 
				
			||||||
 | 
												Id:    "test_id",
 | 
				
			||||||
 | 
												Email: "oauth2@example.com", // should be ignored because of the explicit submitted email
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
											Token: &oauth2.Token{AccessToken: "abc"},
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// add the test provider in the collection
 | 
				
			||||||
 | 
									usersCol.MFA.Enabled = false
 | 
				
			||||||
 | 
									usersCol.OAuth2.Enabled = true
 | 
				
			||||||
 | 
									usersCol.OAuth2.Providers = []core.OAuth2ProviderConfig{{
 | 
				
			||||||
 | 
										Name:         "test",
 | 
				
			||||||
 | 
										ClientId:     "123",
 | 
				
			||||||
 | 
										ClientSecret: "456",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
									if err := app.Save(usersCol); err != nil {
 | 
				
			||||||
 | 
										t.Fatal(err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								ExpectedStatus: 200,
 | 
				
			||||||
 | 
								ExpectedContent: []string{
 | 
				
			||||||
 | 
									`"email":"test_create@example.com"`,
 | 
				
			||||||
 | 
									`"emailVisibility":true`,
 | 
				
			||||||
 | 
									`"name":"test_name"`,
 | 
				
			||||||
 | 
									`"username":"test_username"`,
 | 
				
			||||||
 | 
									`"verified":false`,
 | 
				
			||||||
 | 
									`"rel":"0yxhwia2amd8gec"`,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								NotExpectedContent: []string{
 | 
				
			||||||
 | 
									// hidden fields
 | 
				
			||||||
 | 
									`"tokenKey"`,
 | 
				
			||||||
 | 
									`"password"`,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								ExpectedEvents: map[string]int{
 | 
				
			||||||
 | 
									"*":                             0,
 | 
				
			||||||
 | 
									"OnRecordAuthWithOAuth2Request": 1,
 | 
				
			||||||
 | 
									"OnRecordAuthRequest":           1,
 | 
				
			||||||
 | 
									"OnRecordCreateRequest":         1,
 | 
				
			||||||
 | 
									"OnRecordEnrich":                2, // the auth response and from the create request
 | 
				
			||||||
 | 
									// ---
 | 
				
			||||||
 | 
									"OnModelCreate":              3, // record + authOrigins + externalAuths
 | 
				
			||||||
 | 
									"OnModelCreateExecute":       3,
 | 
				
			||||||
 | 
									"OnModelAfterCreateSuccess":  3,
 | 
				
			||||||
 | 
									"OnRecordCreate":             3,
 | 
				
			||||||
 | 
									"OnRecordCreateExecute":      3,
 | 
				
			||||||
 | 
									"OnRecordAfterCreateSuccess": 3,
 | 
				
			||||||
 | 
									// ---
 | 
				
			||||||
 | 
									"OnModelValidate":  3,
 | 
				
			||||||
 | 
									"OnRecordValidate": 3,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								AfterTestFunc: func(t testing.TB, app *tests.TestApp, res *http.Response) {
 | 
				
			||||||
 | 
									user, err := app.FindFirstRecordByData("users", "username", "test_username")
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										t.Fatal(err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if !user.ValidatePassword("1234567890") {
 | 
				
			||||||
 | 
										t.Fatalf("Expected password %q to be valid", "1234567890")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			Name:   "creating user (with mapped OAuth2 fields and avatarURL->file field)",
 | 
								Name:   "creating user (with mapped OAuth2 fields and avatarURL->file field)",
 | 
				
			||||||
			Method: http.MethodPost,
 | 
								Method: http.MethodPost,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue