mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 18:02:25 -05:00 
			
		
		
		
	[feature] Configurable custom css length (#1827)
* [feature] Make accounts custom css length configurable * test custom css validation
This commit is contained in:
		
					parent
					
						
							
								45f961a9fe
							
						
					
				
			
			
				commit
				
					
						fc524f8cf1
					
				
			
		
					 9 changed files with 174 additions and 89 deletions
				
			
		|  | @ -39,4 +39,11 @@ accounts-reason-required: true | ||||||
| # Options: [true, false] | # Options: [true, false] | ||||||
| # Default: false | # Default: false | ||||||
| accounts-allow-custom-css: false | accounts-allow-custom-css: false | ||||||
|  | 
 | ||||||
|  | # Int. If accounts-allow-custom-css is true, this is the permitted length in characters for | ||||||
|  | # CSS uploaded by accounts on this instance. No effect if accounts-allow-custom-css is false. | ||||||
|  | # | ||||||
|  | # Examples: [500, 5000, 9999] | ||||||
|  | # Default: 10000 | ||||||
|  | accounts-custom-css-length: 10000 | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  | @ -433,6 +433,13 @@ accounts-reason-required: true | ||||||
| # Default: false | # Default: false | ||||||
| accounts-allow-custom-css: false | accounts-allow-custom-css: false | ||||||
| 
 | 
 | ||||||
|  | # Int. If accounts-allow-custom-css is true, this is the permitted length in characters for | ||||||
|  | # CSS uploaded by accounts on this instance. No effect if accounts-allow-custom-css is false. | ||||||
|  | # | ||||||
|  | # Examples: [500, 5000, 9999] | ||||||
|  | # Default: 10000 | ||||||
|  | accounts-custom-css-length: 10000 | ||||||
|  | 
 | ||||||
| ######################## | ######################## | ||||||
| ##### MEDIA CONFIG ##### | ##### MEDIA CONFIG ##### | ||||||
| ######################## | ######################## | ||||||
|  |  | ||||||
|  | @ -85,6 +85,7 @@ type Configuration struct { | ||||||
| 	AccountsApprovalRequired bool `name:"accounts-approval-required" usage:"Do account signups require approval by an admin or moderator before user can log in? If false, new registrations will be automatically approved."` | 	AccountsApprovalRequired bool `name:"accounts-approval-required" usage:"Do account signups require approval by an admin or moderator before user can log in? If false, new registrations will be automatically approved."` | ||||||
| 	AccountsReasonRequired   bool `name:"accounts-reason-required" usage:"Do new account signups require a reason to be submitted on registration?"` | 	AccountsReasonRequired   bool `name:"accounts-reason-required" usage:"Do new account signups require a reason to be submitted on registration?"` | ||||||
| 	AccountsAllowCustomCSS   bool `name:"accounts-allow-custom-css" usage:"Allow accounts to enable custom CSS for their profile pages and statuses."` | 	AccountsAllowCustomCSS   bool `name:"accounts-allow-custom-css" usage:"Allow accounts to enable custom CSS for their profile pages and statuses."` | ||||||
|  | 	AccountsCustomCSSLength  int  `name:"accounts-custom-css-length" usage:"Maximum permitted length (characters) of custom CSS for accounts."` | ||||||
| 
 | 
 | ||||||
| 	MediaImageMaxSize        bytesize.Size `name:"media-image-max-size" usage:"Max size of accepted images in bytes"` | 	MediaImageMaxSize        bytesize.Size `name:"media-image-max-size" usage:"Max size of accepted images in bytes"` | ||||||
| 	MediaVideoMaxSize        bytesize.Size `name:"media-video-max-size" usage:"Max size of accepted videos in bytes"` | 	MediaVideoMaxSize        bytesize.Size `name:"media-video-max-size" usage:"Max size of accepted videos in bytes"` | ||||||
|  |  | ||||||
|  | @ -65,6 +65,7 @@ var Defaults = Configuration{ | ||||||
| 	AccountsApprovalRequired: true, | 	AccountsApprovalRequired: true, | ||||||
| 	AccountsReasonRequired:   true, | 	AccountsReasonRequired:   true, | ||||||
| 	AccountsAllowCustomCSS:   false, | 	AccountsAllowCustomCSS:   false, | ||||||
|  | 	AccountsCustomCSSLength:  10000, | ||||||
| 
 | 
 | ||||||
| 	MediaImageMaxSize:        10 * bytesize.MiB, | 	MediaImageMaxSize:        10 * bytesize.MiB, | ||||||
| 	MediaVideoMaxSize:        40 * bytesize.MiB, | 	MediaVideoMaxSize:        40 * bytesize.MiB, | ||||||
|  |  | ||||||
|  | @ -74,6 +74,31 @@ func GetLogDbQueries() bool { return global.GetLogDbQueries() } | ||||||
| // SetLogDbQueries safely sets the value for global configuration 'LogDbQueries' field | // SetLogDbQueries safely sets the value for global configuration 'LogDbQueries' field | ||||||
| func SetLogDbQueries(v bool) { global.SetLogDbQueries(v) } | func SetLogDbQueries(v bool) { global.SetLogDbQueries(v) } | ||||||
| 
 | 
 | ||||||
|  | // GetLogClientIP safely fetches the Configuration value for state's 'LogClientIP' field | ||||||
|  | func (st *ConfigState) GetLogClientIP() (v bool) { | ||||||
|  | 	st.mutex.Lock() | ||||||
|  | 	v = st.config.LogClientIP | ||||||
|  | 	st.mutex.Unlock() | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetLogClientIP safely sets the Configuration value for state's 'LogClientIP' field | ||||||
|  | func (st *ConfigState) SetLogClientIP(v bool) { | ||||||
|  | 	st.mutex.Lock() | ||||||
|  | 	defer st.mutex.Unlock() | ||||||
|  | 	st.config.LogClientIP = v | ||||||
|  | 	st.reloadToViper() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // LogClientIPFlag returns the flag name for the 'LogClientIP' field | ||||||
|  | func LogClientIPFlag() string { return "log-client-ip" } | ||||||
|  | 
 | ||||||
|  | // GetLogClientIP safely fetches the value for global configuration 'LogClientIP' field | ||||||
|  | func GetLogClientIP() bool { return global.GetLogClientIP() } | ||||||
|  | 
 | ||||||
|  | // SetLogClientIP safely sets the value for global configuration 'LogClientIP' field | ||||||
|  | func SetLogClientIP(v bool) { global.SetLogClientIP(v) } | ||||||
|  | 
 | ||||||
| // GetApplicationName safely fetches the Configuration value for state's 'ApplicationName' field | // GetApplicationName safely fetches the Configuration value for state's 'ApplicationName' field | ||||||
| func (st *ConfigState) GetApplicationName() (v string) { | func (st *ConfigState) GetApplicationName() (v string) { | ||||||
| 	st.mutex.Lock() | 	st.mutex.Lock() | ||||||
|  | @ -924,6 +949,31 @@ func GetAccountsAllowCustomCSS() bool { return global.GetAccountsAllowCustomCSS( | ||||||
| // SetAccountsAllowCustomCSS safely sets the value for global configuration 'AccountsAllowCustomCSS' field | // SetAccountsAllowCustomCSS safely sets the value for global configuration 'AccountsAllowCustomCSS' field | ||||||
| func SetAccountsAllowCustomCSS(v bool) { global.SetAccountsAllowCustomCSS(v) } | func SetAccountsAllowCustomCSS(v bool) { global.SetAccountsAllowCustomCSS(v) } | ||||||
| 
 | 
 | ||||||
|  | // GetAccountsCustomCSSLength safely fetches the Configuration value for state's 'AccountsCustomCSSLength' field | ||||||
|  | func (st *ConfigState) GetAccountsCustomCSSLength() (v int) { | ||||||
|  | 	st.mutex.Lock() | ||||||
|  | 	v = st.config.AccountsCustomCSSLength | ||||||
|  | 	st.mutex.Unlock() | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetAccountsCustomCSSLength safely sets the Configuration value for state's 'AccountsCustomCSSLength' field | ||||||
|  | func (st *ConfigState) SetAccountsCustomCSSLength(v int) { | ||||||
|  | 	st.mutex.Lock() | ||||||
|  | 	defer st.mutex.Unlock() | ||||||
|  | 	st.config.AccountsCustomCSSLength = v | ||||||
|  | 	st.reloadToViper() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // AccountsCustomCSSLengthFlag returns the flag name for the 'AccountsCustomCSSLength' field | ||||||
|  | func AccountsCustomCSSLengthFlag() string { return "accounts-custom-css-length" } | ||||||
|  | 
 | ||||||
|  | // GetAccountsCustomCSSLength safely fetches the value for global configuration 'AccountsCustomCSSLength' field | ||||||
|  | func GetAccountsCustomCSSLength() int { return global.GetAccountsCustomCSSLength() } | ||||||
|  | 
 | ||||||
|  | // SetAccountsCustomCSSLength safely sets the value for global configuration 'AccountsCustomCSSLength' field | ||||||
|  | func SetAccountsCustomCSSLength(v int) { global.SetAccountsCustomCSSLength(v) } | ||||||
|  | 
 | ||||||
| // GetMediaImageMaxSize safely fetches the Configuration value for state's 'MediaImageMaxSize' field | // GetMediaImageMaxSize safely fetches the Configuration value for state's 'MediaImageMaxSize' field | ||||||
| func (st *ConfigState) GetMediaImageMaxSize() (v bytesize.Size) { | func (st *ConfigState) GetMediaImageMaxSize() (v bytesize.Size) { | ||||||
| 	st.mutex.Lock() | 	st.mutex.Lock() | ||||||
|  | @ -3829,28 +3879,3 @@ func GetRequestIDHeader() string { return global.GetRequestIDHeader() } | ||||||
| 
 | 
 | ||||||
| // SetRequestIDHeader safely sets the value for global configuration 'RequestIDHeader' field | // SetRequestIDHeader safely sets the value for global configuration 'RequestIDHeader' field | ||||||
| func SetRequestIDHeader(v string) { global.SetRequestIDHeader(v) } | func SetRequestIDHeader(v string) { global.SetRequestIDHeader(v) } | ||||||
| 
 |  | ||||||
| // GetLogClientIP safely fetches the Configuration value for state's 'LogClientIP' field |  | ||||||
| func (st *ConfigState) GetLogClientIP() (v bool) { |  | ||||||
| 	st.mutex.Lock() |  | ||||||
| 	v = st.config.LogClientIP |  | ||||||
| 	st.mutex.Unlock() |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SetLogClientIP safely sets the Configuration value for state's 'LogClientIP' field |  | ||||||
| func (st *ConfigState) SetLogClientIP(v bool) { |  | ||||||
| 	st.mutex.Lock() |  | ||||||
| 	defer st.mutex.Unlock() |  | ||||||
| 	st.config.LogClientIP = v |  | ||||||
| 	st.reloadToViper() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // LogClientIPFlag returns the flag name for the 'LogClientIP' field |  | ||||||
| func LogClientIPFlag() string { return "log-client-ip" } |  | ||||||
| 
 |  | ||||||
| // GetLogClientIP safely fetches the value for global configuration 'LogClientIP' field |  | ||||||
| func GetLogClientIP() bool { return global.GetLogClientIP() } |  | ||||||
| 
 |  | ||||||
| // SetLogClientIP safely sets the value for global configuration 'LogClientIP' field |  | ||||||
| func SetLogClientIP(v bool) { global.SetLogClientIP(v) } |  | ||||||
|  |  | ||||||
|  | @ -41,7 +41,6 @@ const ( | ||||||
| 	maximumDescriptionLength      = 5000 | 	maximumDescriptionLength      = 5000 | ||||||
| 	maximumSiteTermsLength        = 5000 | 	maximumSiteTermsLength        = 5000 | ||||||
| 	maximumUsernameLength         = 64 | 	maximumUsernameLength         = 64 | ||||||
| 	maximumCustomCSSLength        = 5000 |  | ||||||
| 	maximumEmojiCategoryLength    = 64 | 	maximumEmojiCategoryLength    = 64 | ||||||
| 	maximumProfileFieldLength     = 255 | 	maximumProfileFieldLength     = 255 | ||||||
| 	maximumProfileFields          = 6 | 	maximumProfileFields          = 6 | ||||||
|  | @ -170,9 +169,11 @@ func CustomCSS(customCSS string) error { | ||||||
| 		return errors.New("accounts-allow-custom-css is not enabled for this instance") | 		return errors.New("accounts-allow-custom-css is not enabled for this instance") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	maximumCustomCSSLength := config.GetAccountsCustomCSSLength() | ||||||
| 	if length := len([]rune(customCSS)); length > maximumCustomCSSLength { | 	if length := len([]rune(customCSS)); length > maximumCustomCSSLength { | ||||||
| 		return fmt.Errorf("custom_css must be less than %d characters, but submitted custom_css was %d characters", maximumCustomCSSLength, length) | 		return fmt.Errorf("custom_css must be less than %d characters, but submitted custom_css was %d characters", maximumCustomCSSLength, length) | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -22,8 +22,8 @@ import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"testing" | 	"testing" | ||||||
| 
 | 
 | ||||||
| 	"github.com/stretchr/testify/assert" |  | ||||||
| 	"github.com/stretchr/testify/suite" | 	"github.com/stretchr/testify/suite" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/validate" | 	"github.com/superseriousbusiness/gotosocial/internal/validate" | ||||||
| ) | ) | ||||||
|  | @ -44,43 +44,43 @@ func (suite *ValidationTestSuite) TestCheckPasswordStrength() { | ||||||
| 	var err error | 	var err error | ||||||
| 
 | 
 | ||||||
| 	err = validate.NewPassword(empty) | 	err = validate.NewPassword(empty) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("no password provided"), err) | 		suite.Equal(errors.New("no password provided"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.NewPassword(terriblePassword) | 	err = validate.NewPassword(terriblePassword) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("password is only 62% strength, try including more special characters, using uppercase letters, using numbers or using a longer password"), err) | 		suite.Equal(errors.New("password is only 62% strength, try including more special characters, using uppercase letters, using numbers or using a longer password"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.NewPassword(weakPassword) | 	err = validate.NewPassword(weakPassword) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("password is only 95% strength, try including more special characters, using numbers or using a longer password"), err) | 		suite.Equal(errors.New("password is only 95% strength, try including more special characters, using numbers or using a longer password"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.NewPassword(shortPassword) | 	err = validate.NewPassword(shortPassword) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("password is only 39% strength, try including more special characters or using a longer password"), err) | 		suite.Equal(errors.New("password is only 39% strength, try including more special characters or using a longer password"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.NewPassword(specialPassword) | 	err = validate.NewPassword(specialPassword) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("password is only 53% strength, try including more special characters or using a longer password"), err) | 		suite.Equal(errors.New("password is only 53% strength, try including more special characters or using a longer password"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.NewPassword(longPassword) | 	err = validate.NewPassword(longPassword) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.NewPassword(tooLong) | 	err = validate.NewPassword(tooLong) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("password should be no more than 256 chars"), err) | 		suite.Equal(errors.New("password should be no more than 256 chars"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.NewPassword(strongPassword) | 	err = validate.NewPassword(strongPassword) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -133,28 +133,28 @@ func (suite *ValidationTestSuite) TestValidateEmail() { | ||||||
| 	var err error | 	var err error | ||||||
| 
 | 
 | ||||||
| 	err = validate.Email(empty) | 	err = validate.Email(empty) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("no email provided"), err) | 		suite.Equal(errors.New("no email provided"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.Email(notAnEmailAddress) | 	err = validate.Email(notAnEmailAddress) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("mail: missing '@' or angle-addr"), err) | 		suite.Equal(errors.New("mail: missing '@' or angle-addr"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.Email(almostAnEmailAddress) | 	err = validate.Email(almostAnEmailAddress) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("mail: no angle-addr"), err) | 		suite.Equal(errors.New("mail: no angle-addr"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.Email(aWebsite) | 	err = validate.Email(aWebsite) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("mail: missing '@' or angle-addr"), err) | 		suite.Equal(errors.New("mail: missing '@' or angle-addr"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.Email(emailAddress) | 	err = validate.Email(emailAddress) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -171,48 +171,48 @@ func (suite *ValidationTestSuite) TestValidateLanguage() { | ||||||
| 	var err error | 	var err error | ||||||
| 
 | 
 | ||||||
| 	err = validate.Language(empty) | 	err = validate.Language(empty) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("no language provided"), err) | 		suite.Equal(errors.New("no language provided"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.Language(notALanguage) | 	err = validate.Language(notALanguage) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("language: tag is not well-formed"), err) | 		suite.Equal(errors.New("language: tag is not well-formed"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.Language(english) | 	err = validate.Language(english) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.Language(capitalEnglish) | 	err = validate.Language(capitalEnglish) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.Language(arabic3Letters) | 	err = validate.Language(arabic3Letters) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.Language(mixedCapsEnglish) | 	err = validate.Language(mixedCapsEnglish) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.Language(englishUS) | 	err = validate.Language(englishUS) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("language: tag is not well-formed"), err) | 		suite.Equal(errors.New("language: tag is not well-formed"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.Language(dutch) | 	err = validate.Language(dutch) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.Language(german) | 	err = validate.Language(german) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -226,49 +226,49 @@ func (suite *ValidationTestSuite) TestValidateReason() { | ||||||
| 
 | 
 | ||||||
| 	// check with no reason required | 	// check with no reason required | ||||||
| 	err = validate.SignUpReason(empty, false) | 	err = validate.SignUpReason(empty, false) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.SignUpReason(badReason, false) | 	err = validate.SignUpReason(badReason, false) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.SignUpReason(tooLong, false) | 	err = validate.SignUpReason(tooLong, false) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.SignUpReason(goodReason, false) | 	err = validate.SignUpReason(goodReason, false) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.SignUpReason(unicode, false) | 	err = validate.SignUpReason(unicode, false) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// check with reason required | 	// check with reason required | ||||||
| 	err = validate.SignUpReason(empty, true) | 	err = validate.SignUpReason(empty, true) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("no reason provided"), err) | 		suite.Equal(errors.New("no reason provided"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.SignUpReason(badReason, true) | 	err = validate.SignUpReason(badReason, true) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("reason should be at least 40 chars but 'because' was 7"), err) | 		suite.Equal(errors.New("reason should be at least 40 chars but 'because' was 7"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.SignUpReason(tooLong, true) | 	err = validate.SignUpReason(tooLong, true) | ||||||
| 	if assert.Error(suite.T(), err) { | 	if suite.Error(err) { | ||||||
| 		assert.Equal(suite.T(), errors.New("reason should be no more than 500 chars but given reason was 600"), err) | 		suite.Equal(errors.New("reason should be no more than 500 chars but given reason was 600"), err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = validate.SignUpReason(goodReason, true) | 	err = validate.SignUpReason(goodReason, true) | ||||||
| 	if assert.NoError(suite.T(), err) { | 	if suite.NoError(err) { | ||||||
| 		assert.Equal(suite.T(), nil, err) | 		suite.Equal(nil, err) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -302,6 +302,46 @@ func (suite *ValidationTestSuite) TestValidateProfileField() { | ||||||
| 	suite.Len(dodgyFields[0].Value, 255) | 	suite.Len(dodgyFields[0].Value, 255) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (suite *ValidationTestSuite) TestValidateCustomCSSDisabled() { | ||||||
|  | 	config.SetAccountsAllowCustomCSS(false) | ||||||
|  | 
 | ||||||
|  | 	err := validate.CustomCSS("this will fail") | ||||||
|  | 	suite.EqualError(err, "accounts-allow-custom-css is not enabled for this instance") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *ValidationTestSuite) TestValidateCustomCSSEnabled() { | ||||||
|  | 	config.SetAccountsAllowCustomCSS(true) | ||||||
|  | 
 | ||||||
|  | 	err := validate.CustomCSS("this will pass") | ||||||
|  | 	suite.NoError(err) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *ValidationTestSuite) TestValidateCustomCSSTooLong() { | ||||||
|  | 	config.SetAccountsAllowCustomCSS(true) | ||||||
|  | 	config.SetAccountsCustomCSSLength(5) | ||||||
|  | 
 | ||||||
|  | 	err := validate.CustomCSS("this will fail") | ||||||
|  | 	suite.EqualError(err, "custom_css must be less than 5 characters, but submitted custom_css was 14 characters") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *ValidationTestSuite) TestValidateCustomCSSTooLongZalgo() { | ||||||
|  | 	config.SetAccountsAllowCustomCSS(true) | ||||||
|  | 	config.SetAccountsCustomCSSLength(5) | ||||||
|  | 	zalgo := "p̵̹̜͇̺̜̱͊̓̈́͛̀͊͘͜e̷̡̱̲̼̪̗̙̐͐̃́̄̉͛̔e̷̞̰̜̲̥̘̻͔̜̞̬͚͋̊͑͗̅̓͛͗̎̃̈́̐̂̕͝ ̷̨̢̡̱̖̤͇̻͕̲̤̞̑ͅp̶̰̜̟̠̏̇̇̆̐̒͋̔͘ḛ̵̾͘ę̷̝͙͕͓͓̱̠̤̳̻̜̗͖̞͙̻̆̓̄͋̎͊̀̋̿́̐͛͗̄̈́̚͠ ̵̨̨̫͕̲͚̮͕̳̉̾̔̍͐p̶̘̞̠̘̎̓̍̑̀͗̃̈́͂́̈́͆͘͜͝͝o̶̜͛̒͒̉̑͒̿͗̐̃͝o̵̼̒͌̓ ̵̢̗̦͔͉͈̰̘̋̃̐̑̅̽̏̄̅͐͆̔͊̃̋͝p̵̩̱̆̆͂̂͛̓̋̅͝o̶̪̰̲̝̻̳̦̮̮͔̒ͅơ̸̧̨̟͇̪̰̜̠̦͇̇̎͗̏̏̈́͂̉̏͐́̃̀͆͠ͅ" | ||||||
|  | 
 | ||||||
|  | 	err := validate.CustomCSS(zalgo) | ||||||
|  | 	suite.EqualError(err, "custom_css must be less than 5 characters, but submitted custom_css was 275 characters") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *ValidationTestSuite) TestValidateCustomCSSTooLongUnicode() { | ||||||
|  | 	config.SetAccountsAllowCustomCSS(true) | ||||||
|  | 	config.SetAccountsCustomCSSLength(5) | ||||||
|  | 	unicode := "⎾⎿⏀⏁⏂⏃⏄⏅⏆⏇" | ||||||
|  | 
 | ||||||
|  | 	err := validate.CustomCSS(unicode) | ||||||
|  | 	suite.EqualError(err, "custom_css must be less than 5 characters, but submitted custom_css was 10 characters") | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func TestValidationTestSuite(t *testing.T) { | func TestValidationTestSuite(t *testing.T) { | ||||||
| 	suite.Run(t, new(ValidationTestSuite)) | 	suite.Run(t, new(ValidationTestSuite)) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ EXPECT=$(cat <<"EOF" | ||||||
|     "account-domain": "peepee", |     "account-domain": "peepee", | ||||||
|     "accounts-allow-custom-css": true, |     "accounts-allow-custom-css": true, | ||||||
|     "accounts-approval-required": false, |     "accounts-approval-required": false, | ||||||
|  |     "accounts-custom-css-length": 5000, | ||||||
|     "accounts-reason-required": false, |     "accounts-reason-required": false, | ||||||
|     "accounts-registration-open": true, |     "accounts-registration-open": true, | ||||||
|     "advanced-cookies-samesite": "strict", |     "advanced-cookies-samesite": "strict", | ||||||
|  | @ -207,6 +208,7 @@ GTS_INSTANCE_EXPOSE_SUSPENDED_WEB=true \ | ||||||
| GTS_INSTANCE_EXPOSE_PUBLIC_TIMELINE=true \ | GTS_INSTANCE_EXPOSE_PUBLIC_TIMELINE=true \ | ||||||
| GTS_INSTANCE_DELIVER_TO_SHARED_INBOXES=false \ | GTS_INSTANCE_DELIVER_TO_SHARED_INBOXES=false \ | ||||||
| GTS_ACCOUNTS_ALLOW_CUSTOM_CSS=true \ | GTS_ACCOUNTS_ALLOW_CUSTOM_CSS=true \ | ||||||
|  | GTS_ACCOUNTS_CUSTOM_CSS_LENGTH=5000 \ | ||||||
| GTS_ACCOUNTS_REGISTRATION_OPEN=true \ | GTS_ACCOUNTS_REGISTRATION_OPEN=true \ | ||||||
| GTS_ACCOUNTS_APPROVAL_REQUIRED=false \ | GTS_ACCOUNTS_APPROVAL_REQUIRED=false \ | ||||||
| GTS_ACCOUNTS_REASON_REQUIRED=false \ | GTS_ACCOUNTS_REASON_REQUIRED=false \ | ||||||
|  |  | ||||||
|  | @ -71,6 +71,7 @@ var testDefaults = config.Configuration{ | ||||||
| 	AccountsApprovalRequired: true, | 	AccountsApprovalRequired: true, | ||||||
| 	AccountsReasonRequired:   true, | 	AccountsReasonRequired:   true, | ||||||
| 	AccountsAllowCustomCSS:   true, | 	AccountsAllowCustomCSS:   true, | ||||||
|  | 	AccountsCustomCSSLength:  10000, | ||||||
| 
 | 
 | ||||||
| 	MediaImageMaxSize:        10485760, // 10mb | 	MediaImageMaxSize:        10485760, // 10mb | ||||||
| 	MediaVideoMaxSize:        41943040, // 40mb | 	MediaVideoMaxSize:        41943040, // 40mb | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue