| 
									
										
										
										
											2023-03-12 16:00:57 +01:00
										 |  |  | // GoToSocial | 
					
						
							|  |  |  | // Copyright (C) GoToSocial Authors admin@gotosocial.org | 
					
						
							|  |  |  | // SPDX-License-Identifier: AGPL-3.0-or-later | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | // GNU Affero General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2021-07-05 13:23:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | package account | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2021-07-05 13:23:03 +02:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2021-10-31 15:46:23 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | 
					
						
							| 
									
										
										
										
											2021-07-05 13:23:03 +02:00
										 |  |  | 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" | 
					
						
							| 
									
										
										
										
											2021-12-07 13:31:39 +01:00
										 |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/config" | 
					
						
							| 
									
										
										
										
											2022-06-08 20:38:03 +02:00
										 |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 
					
						
							| 
									
										
										
										
											2021-07-05 13:23:03 +02:00
										 |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 
					
						
							| 
									
										
										
										
											2021-10-31 15:46:23 +01:00
										 |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | 
					
						
							| 
									
										
										
										
											2021-07-26 20:25:54 +02:00
										 |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/text" | 
					
						
							| 
									
										
										
										
											2021-07-05 13:23:03 +02:00
										 |  |  | 	"github.com/superseriousbusiness/oauth2/v4" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-23 12:33:17 +02:00
										 |  |  | // Create processes the given form for creating a new account, | 
					
						
							|  |  |  | // returning an oauth token for that account if successful. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2023-08-07 01:25:54 -07:00
										 |  |  | // Precondition: the form's fields should have already been validated and normalized by the caller. | 
					
						
							| 
									
										
										
										
											2023-07-23 12:33:17 +02:00
										 |  |  | func (p *Processor) Create( | 
					
						
							|  |  |  | 	ctx context.Context, | 
					
						
							|  |  |  | 	appToken oauth2.TokenInfo, | 
					
						
							|  |  |  | 	app *gtsmodel.Application, | 
					
						
							|  |  |  | 	form *apimodel.AccountCreateRequest, | 
					
						
							|  |  |  | ) (*apimodel.Token, gtserror.WithCode) { | 
					
						
							| 
									
										
										
										
											2023-03-01 18:26:53 +00:00
										 |  |  | 	emailAvailable, err := p.state.DB.IsEmailAvailable(ctx, form.Email) | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2023-07-23 12:33:17 +02:00
										 |  |  | 		err := fmt.Errorf("db error checking email availability: %w", err) | 
					
						
							|  |  |  | 		return nil, gtserror.NewErrorInternalError(err) | 
					
						
							| 
									
										
										
										
											2021-07-05 13:23:03 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	if !emailAvailable { | 
					
						
							| 
									
										
										
										
											2023-07-23 12:33:17 +02:00
										 |  |  | 		err := fmt.Errorf("email address %s is not available", form.Email) | 
					
						
							|  |  |  | 		return nil, gtserror.NewErrorConflict(err, err.Error()) | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-07-05 13:23:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-01 18:26:53 +00:00
										 |  |  | 	usernameAvailable, err := p.state.DB.IsUsernameAvailable(ctx, form.Username) | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2023-07-23 12:33:17 +02:00
										 |  |  | 		err := fmt.Errorf("db error checking username availability: %w", err) | 
					
						
							|  |  |  | 		return nil, gtserror.NewErrorInternalError(err) | 
					
						
							| 
									
										
										
										
											2021-07-05 13:23:03 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	if !usernameAvailable { | 
					
						
							| 
									
										
										
										
											2023-07-23 12:33:17 +02:00
										 |  |  | 		err := fmt.Errorf("username %s is not available", form.Username) | 
					
						
							|  |  |  | 		return nil, gtserror.NewErrorConflict(err, err.Error()) | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-07-05 13:23:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-23 12:33:17 +02:00
										 |  |  | 	// Only store reason if one is required. | 
					
						
							|  |  |  | 	var reason string | 
					
						
							|  |  |  | 	if config.GetAccountsReasonRequired() { | 
					
						
							|  |  |  | 		reason = form.Reason | 
					
						
							| 
									
										
										
										
											2021-07-05 13:23:03 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-23 12:33:17 +02:00
										 |  |  | 	user, err := p.state.DB.NewSignup(ctx, gtsmodel.NewSignup{ | 
					
						
							|  |  |  | 		Username:    form.Username, | 
					
						
							|  |  |  | 		Email:       form.Email, | 
					
						
							|  |  |  | 		Password:    form.Password, | 
					
						
							|  |  |  | 		Reason:      text.SanitizePlaintext(reason), | 
					
						
							|  |  |  | 		PreApproved: !config.GetAccountsApprovalRequired(), // Mark as approved if no approval required. | 
					
						
							|  |  |  | 		SignUpIP:    form.IP, | 
					
						
							|  |  |  | 		Locale:      form.Locale, | 
					
						
							|  |  |  | 		AppID:       app.ID, | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2021-07-05 13:23:03 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2023-07-23 12:33:17 +02:00
										 |  |  | 		err := fmt.Errorf("db error creating new signup: %w", err) | 
					
						
							|  |  |  | 		return nil, gtserror.NewErrorInternalError(err) | 
					
						
							| 
									
										
										
										
											2021-07-05 13:23:03 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-23 12:33:17 +02:00
										 |  |  | 	// Generate access token *before* doing side effects; we | 
					
						
							|  |  |  | 	// don't want to process side effects if something borks. | 
					
						
							|  |  |  | 	accessToken, err := p.oauthServer.GenerateUserAccessToken(ctx, appToken, app.ClientSecret, user.ID) | 
					
						
							| 
									
										
										
										
											2021-07-05 13:23:03 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2023-07-23 12:33:17 +02:00
										 |  |  | 		err := fmt.Errorf("error creating new access token for user %s: %w", user.ID, err) | 
					
						
							|  |  |  | 		return nil, gtserror.NewErrorInternalError(err) | 
					
						
							| 
									
										
										
										
											2021-10-31 15:46:23 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-23 12:33:17 +02:00
										 |  |  | 	// There are side effects for creating a new account | 
					
						
							|  |  |  | 	// (confirmation emails etc), perform these async. | 
					
						
							| 
									
										
										
										
											2023-03-01 18:26:53 +00:00
										 |  |  | 	p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{ | 
					
						
							| 
									
										
										
										
											2021-10-31 15:46:23 +01:00
										 |  |  | 		APObjectType:   ap.ObjectProfile, | 
					
						
							|  |  |  | 		APActivityType: ap.ActivityCreate, | 
					
						
							|  |  |  | 		GTSModel:       user.Account, | 
					
						
							|  |  |  | 		OriginAccount:  user.Account, | 
					
						
							| 
									
										
										
										
											2022-04-28 13:23:11 +01:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2021-10-31 15:46:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-05 13:23:03 +02:00
										 |  |  | 	return &apimodel.Token{ | 
					
						
							|  |  |  | 		AccessToken: accessToken.GetAccess(), | 
					
						
							|  |  |  | 		TokenType:   "Bearer", | 
					
						
							|  |  |  | 		Scope:       accessToken.GetScope(), | 
					
						
							|  |  |  | 		CreatedAt:   accessToken.GetAccessCreateAt().Unix(), | 
					
						
							|  |  |  | 	}, nil | 
					
						
							|  |  |  | } |