Linting.
This commit is contained in:
		
							
								
								
									
										11
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								.drone.yml
									
									
									
									
									
								
							| @@ -20,14 +20,18 @@ steps: | ||||
|       CGO_ENABLED: 0 | ||||
|     commands: | ||||
|       - golangci-lint run | ||||
|     depends_on: | ||||
|       - notify-start | ||||
|  | ||||
|   - name: test | ||||
|     image: golang:1.13.1-alpine | ||||
|     image: golang:1.13.5-alpine | ||||
|     environment: | ||||
|       GOFLAGS: -mod=vendor | ||||
|       CGO_ENABLED: 0 | ||||
|     commands: | ||||
|       - go test ./... | ||||
|     depends_on: | ||||
|       - notify-start | ||||
|  | ||||
|   - name: docker | ||||
|     image: plugins/docker | ||||
| @@ -40,6 +44,9 @@ steps: | ||||
|         from_secret: dockerhub_password | ||||
|       repo: pztrn/fastpastebin | ||||
|       auto_tag: true | ||||
|     depends_on: | ||||
|       - lint | ||||
|       - test | ||||
|  | ||||
|   - name: notify-end | ||||
|     when: | ||||
| @@ -58,3 +65,5 @@ steps: | ||||
|         {{ else }} | ||||
|         **{{repo.name}}#{{build.number}}@{{build.commit}}** failed. See {{build.link}}. | ||||
|         {{/success}}" | ||||
|     depends_on: | ||||
|       - docker | ||||
|   | ||||
							
								
								
									
										18
									
								
								.golangci.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								.golangci.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| run: | ||||
|   deadline: 5m | ||||
| linters: | ||||
|   enable-all: true | ||||
|   disable: | ||||
|     # Because globals might exist, but according to our codestyle they | ||||
|     # should be lowercased and considered as unexported. | ||||
|     - gochecknoglobals | ||||
|     # While it might be useful it'll create more problems that will solve. | ||||
|     - gocritic | ||||
|     # Complains about main() lengths, which isn't an issue. | ||||
|     - funlen | ||||
| linters-settings: | ||||
|   lll: | ||||
|     line-length: 420 | ||||
|   gocyclo: | ||||
|     min-complexity: 40 | ||||
|    | ||||
| @@ -31,7 +31,7 @@ import ( | ||||
| 	"syscall" | ||||
|  | ||||
| 	// local | ||||
| 	"go.dev.pztrn.name/fastpastebin/domains/database_not_available" | ||||
| 	"go.dev.pztrn.name/fastpastebin/domains/dbnotavailable" | ||||
| 	"go.dev.pztrn.name/fastpastebin/domains/indexpage" | ||||
| 	"go.dev.pztrn.name/fastpastebin/domains/pastes" | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/captcha" | ||||
| @@ -61,14 +61,16 @@ func main() { | ||||
|  | ||||
| 	captcha.New(c) | ||||
|  | ||||
| 	database_not_available.New(c) | ||||
| 	dbnotavailable.New(c) | ||||
| 	indexpage.New(c) | ||||
| 	pastes.New(c) | ||||
|  | ||||
| 	// CTRL+C handler. | ||||
| 	signalHandler := make(chan os.Signal, 1) | ||||
| 	shutdownDone := make(chan bool, 1) | ||||
|  | ||||
| 	signal.Notify(signalHandler, os.Interrupt, syscall.SIGTERM) | ||||
|  | ||||
| 	go func() { | ||||
| 		<-signalHandler | ||||
| 		c.Shutdown() | ||||
|   | ||||
| @@ -22,7 +22,7 @@ | ||||
| // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE | ||||
| // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
| 
 | ||||
| package database_not_available | ||||
| package dbnotavailable | ||||
| 
 | ||||
| import ( | ||||
| 	// stdlib | ||||
| @@ -22,7 +22,7 @@ | ||||
| // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE | ||||
| // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
| 
 | ||||
| package database_not_available | ||||
| package dbnotavailable | ||||
| 
 | ||||
| import ( | ||||
| 	// local | ||||
| @@ -33,7 +33,7 @@ var ( | ||||
| 	c *context.Context | ||||
| ) | ||||
| 
 | ||||
| // New initializes pastes package and adds neccessary HTTP and API | ||||
| // New initializes pastes package and adds necessary HTTP and API | ||||
| // endpoints. | ||||
| func New(cc *context.Context) { | ||||
| 	c = cc | ||||
| @@ -33,7 +33,7 @@ var ( | ||||
| 	c *context.Context | ||||
| ) | ||||
|  | ||||
| // New initializes pastes package and adds neccessary HTTP and API | ||||
| // New initializes pastes package and adds necessary HTTP and API | ||||
| // endpoints. | ||||
| func New(cc *context.Context) { | ||||
| 	c = cc | ||||
|   | ||||
| @@ -40,7 +40,7 @@ var ( | ||||
| 	c *context.Context | ||||
| ) | ||||
|  | ||||
| // New initializes pastes package and adds neccessary HTTP and API | ||||
| // New initializes pastes package and adds necessary HTTP and API | ||||
| // endpoints. | ||||
| func New(cc *context.Context) { | ||||
| 	c = cc | ||||
|   | ||||
| @@ -34,12 +34,6 @@ const ( | ||||
| // for some cases, e.g. public paste won't check for timestamp and cookie | ||||
| // value (they both will be ignored), but private will. | ||||
| func pasteGetData(pasteID int, timestamp int64, cookieValue string) (*structs.Paste, string) { | ||||
| 	// We should check if database connection available. | ||||
| 	//dbConn := c.Database.GetDatabaseConnection() | ||||
| 	//if c.Config.Database.Type != "flatfiles" && dbConn == nil { | ||||
| 	//	return ec.Redirect(http.StatusFound, "/database_not_available") | ||||
| 	//} | ||||
|  | ||||
| 	// Get paste. | ||||
| 	paste, err1 := c.Database.GetPaste(pasteID) | ||||
| 	if err1 != nil { | ||||
| @@ -91,21 +85,25 @@ func pasteGETWebInterface(ec echo.Context) error { | ||||
| 	// If passed timestamp is invalid (isn't a real UNIX timestamp) we | ||||
| 	// will show 404 Not Found error and spam about that in logs. | ||||
| 	var timestamp int64 | ||||
|  | ||||
| 	tsProvidedStr := ec.Param("timestamp") | ||||
| 	if tsProvidedStr != "" { | ||||
| 		tsProvided, err := strconv.ParseInt(tsProvidedStr, 10, 64) | ||||
| 		if err != nil { | ||||
| 			c.Logger.Error().Err(err).Int("paste ID", pasteID).Int64("provided timestamp", tsProvided).Msg("Invalid timestamp provided for getting private paste") | ||||
|  | ||||
| 			errtpl := templater.GetErrorTemplate(ec, "Paste #"+pasteIDStr+" not found") | ||||
|  | ||||
| 			return ec.HTML(http.StatusBadRequest, errtpl) | ||||
| 		} else { | ||||
| 			timestamp = tsProvided | ||||
| 		} | ||||
|  | ||||
| 		timestamp = tsProvided | ||||
| 	} | ||||
|  | ||||
| 	// Check if we have "PASTE-PASTEID" cookie defined. It is required | ||||
| 	// for private pastes. | ||||
| 	var cookieValue string | ||||
|  | ||||
| 	cookie, err1 := ec.Cookie("PASTE-" + pasteIDStr) | ||||
| 	if err1 == nil { | ||||
| 		cookieValue = cookie.Value | ||||
| @@ -137,6 +135,7 @@ func pasteGETWebInterface(ec echo.Context) error { | ||||
| 	if paste.KeepFor != 0 && paste.KeepForUnitType != 0 { | ||||
| 		pasteExpirationString = paste.GetExpirationTime().Format("2006-01-02 @ 15:04:05") + " UTC" | ||||
| 	} | ||||
|  | ||||
| 	pasteData["pasteExpiration"] = pasteExpirationString | ||||
|  | ||||
| 	if paste.Private { | ||||
| @@ -170,10 +169,12 @@ func pasteGETWebInterface(ec echo.Context) error { | ||||
| 	} | ||||
| 	// Create buffer and format into it. | ||||
| 	buf := new(bytes.Buffer) | ||||
|  | ||||
| 	err4 := formatter.Format(buf, style, lexered) | ||||
| 	if err4 != nil { | ||||
| 		c.Logger.Error().Err(err4).Msg("Failed to format paste data") | ||||
| 	} | ||||
|  | ||||
| 	pasteData["pastedata"] = buf.String() | ||||
|  | ||||
| 	// Get template and format it. | ||||
| @@ -194,7 +195,9 @@ func pastePasswordedVerifyGet(ec echo.Context) error { | ||||
| 	paste, err1 := c.Database.GetPaste(pasteID) | ||||
| 	if err1 != nil { | ||||
| 		c.Logger.Error().Err(err1).Int("paste ID", pasteID).Msg("Failed to get paste data") | ||||
|  | ||||
| 		errtpl := templater.GetErrorTemplate(ec, "Paste #"+pasteIDRaw+" not found") | ||||
|  | ||||
| 		return ec.HTML(http.StatusBadRequest, errtpl) | ||||
| 	} | ||||
|  | ||||
| @@ -229,6 +232,7 @@ func pastePasswordedVerifyGet(ec echo.Context) error { | ||||
| func pastePasswordedVerifyPost(ec echo.Context) error { | ||||
| 	// We should check if database connection available. | ||||
| 	dbConn := c.Database.GetDatabaseConnection() | ||||
| 	// nolint | ||||
| 	if c.Config.Database.Type != "flatfiles" && dbConn == nil { | ||||
| 		return ec.Redirect(http.StatusFound, "/database_not_available") | ||||
| 	} | ||||
| @@ -245,13 +249,16 @@ func pastePasswordedVerifyPost(ec echo.Context) error { | ||||
| 	if err1 != nil { | ||||
| 		c.Logger.Error().Err(err1).Int("paste ID", pasteID).Msg("Failed to get paste") | ||||
| 		errtpl := templater.GetErrorTemplate(ec, "Paste #"+strconv.Itoa(pasteID)+" not found") | ||||
|  | ||||
| 		return ec.HTML(http.StatusBadRequest, errtpl) | ||||
| 	} | ||||
|  | ||||
| 	params, err2 := ec.FormParams() | ||||
| 	if err2 != nil { | ||||
| 		c.Logger.Debug().Msg("No form parameters passed") | ||||
|  | ||||
| 		errtpl := templater.GetErrorTemplate(ec, "Paste #"+strconv.Itoa(pasteID)+" not found") | ||||
|  | ||||
| 		return ec.HTML(http.StatusBadRequest, errtpl) | ||||
| 	} | ||||
|  | ||||
| @@ -268,7 +275,8 @@ func pastePasswordedVerifyPost(ec echo.Context) error { | ||||
| 	} | ||||
|  | ||||
| 	errtpl := templater.GetErrorTemplate(ec, "Invalid password. Please, try again.") | ||||
| 	return ec.HTML(http.StatusBadRequest, string(errtpl)) | ||||
|  | ||||
| 	return ec.HTML(http.StatusBadRequest, errtpl) | ||||
| } | ||||
|  | ||||
| // GET for "/pastes/:id/raw", raw paste output. | ||||
| @@ -301,18 +309,23 @@ func pasteRawGETWebInterface(ec echo.Context) error { | ||||
| 	// Check if we have a private paste and it's parameters are correct. | ||||
| 	if paste.Private { | ||||
| 		tsProvidedStr := ec.Param("timestamp") | ||||
|  | ||||
| 		tsProvided, err2 := strconv.ParseInt(tsProvidedStr, 10, 64) | ||||
| 		if err2 != nil { | ||||
| 			c.Logger.Error().Err(err2).Int("paste ID", pasteID).Str("provided timestamp", tsProvidedStr).Msg("Invalid timestamp provided for getting private paste") | ||||
|  | ||||
| 			return ec.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found") | ||||
| 		} | ||||
|  | ||||
| 		pasteTs := paste.CreatedAt.Unix() | ||||
| 		if tsProvided != pasteTs { | ||||
| 			c.Logger.Error().Int("paste ID", pasteID).Int64("provided timestamp", tsProvided).Int64("paste timestamp", pasteTs).Msg("Incorrect timestamp provided for private paste") | ||||
|  | ||||
| 			return ec.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// nolint | ||||
| 	// ToDo: figure out how to handle passworded pastes here. | ||||
| 	// Return error for now. | ||||
| 	if paste.Password != "" { | ||||
|   | ||||
| @@ -31,28 +31,37 @@ func pastePOSTWebInterface(ec echo.Context) error { | ||||
| 	params, err := ec.FormParams() | ||||
| 	if err != nil { | ||||
| 		c.Logger.Error().Msg("Passed paste form is empty") | ||||
|  | ||||
| 		errtpl := templater.GetErrorTemplate(ec, "Cannot create empty paste") | ||||
|  | ||||
| 		return ec.HTML(http.StatusBadRequest, errtpl) | ||||
| 	} | ||||
|  | ||||
| 	c.Logger.Debug().Msgf("Received parameters: %+v", params) | ||||
|  | ||||
| 	// Do nothing if paste contents is empty. | ||||
| 	if len(params["paste-contents"][0]) == 0 { | ||||
| 		c.Logger.Debug().Msg("Empty paste submitted, ignoring") | ||||
|  | ||||
| 		errtpl := templater.GetErrorTemplate(ec, "Empty pastes aren't allowed.") | ||||
|  | ||||
| 		return ec.HTML(http.StatusBadRequest, errtpl) | ||||
| 	} | ||||
|  | ||||
| 	// nolint | ||||
| 	if !strings.ContainsAny(params["paste-keep-for"][0], "Mmhd") && params["paste-keep-for"][0] != "forever" { | ||||
| 		c.Logger.Debug().Str("field value", params["paste-keep-for"][0]).Msg("'Keep paste for' field have invalid value") | ||||
| 		errtpl := templater.GetErrorTemplate(ec, "Invalid 'Paste should be available for' parameter passed. Please do not try to hack us ;).") | ||||
|  | ||||
| 		return ec.HTML(http.StatusBadRequest, errtpl) | ||||
| 	} | ||||
|  | ||||
| 	// Verify captcha. | ||||
| 	if !captcha.Verify(params["paste-captcha-id"][0], params["paste-captcha-solution"][0]) { | ||||
| 		c.Logger.Debug().Str("captcha ID", params["paste-captcha-id"][0]).Str("captcha solution", params["paste-captcha-solution"][0]).Msg("Invalid captcha solution") | ||||
|  | ||||
| 		errtpl := templater.GetErrorTemplate(ec, "Invalid captcha solution.") | ||||
|  | ||||
| 		return ec.HTML(http.StatusBadRequest, errtpl) | ||||
| 	} | ||||
|  | ||||
| @@ -70,26 +79,33 @@ func pastePOSTWebInterface(ec echo.Context) error { | ||||
| 	// Defaulting to "forever". | ||||
| 	keepFor := 0 | ||||
| 	keepForUnit := 0 | ||||
|  | ||||
| 	if params["paste-keep-for"][0] != "forever" { | ||||
| 		keepForUnitRegex := regexp.MustCompile("[Mmhd]") | ||||
|  | ||||
| 		keepForRaw := regexInts.FindAllString(params["paste-keep-for"][0], 1)[0] | ||||
|  | ||||
| 		var err error | ||||
|  | ||||
| 		keepFor, err = strconv.Atoi(keepForRaw) | ||||
| 		if err != nil { | ||||
| 			if params["paste-keep-for"][0] == "forever" { | ||||
| 				c.Logger.Debug().Msg("Keeping paste forever!") | ||||
|  | ||||
| 				keepFor = 0 | ||||
| 			} else { | ||||
| 				c.Logger.Debug().Err(err).Msg("Failed to parse 'Keep for' integer") | ||||
|  | ||||
| 				errtpl := templater.GetErrorTemplate(ec, "Invalid 'Paste should be available for' parameter passed. Please do not try to hack us ;).") | ||||
|  | ||||
| 				return ec.HTML(http.StatusBadRequest, errtpl) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		keepForUnitRaw := keepForUnitRegex.FindAllString(params["paste-keep-for"][0], 1)[0] | ||||
| 		keepForUnit = structs.PASTE_KEEPS_CORELLATION[keepForUnitRaw] | ||||
| 		keepForUnit = structs.PasteKeepsCorellation[keepForUnitRaw] | ||||
| 	} | ||||
|  | ||||
| 	paste.KeepFor = keepFor | ||||
| 	paste.KeepForUnitType = keepForUnit | ||||
|  | ||||
| @@ -107,6 +123,7 @@ func pastePOSTWebInterface(ec echo.Context) error { | ||||
| 	paste.Private = false | ||||
| 	privateCheckbox, privateCheckboxFound := params["paste-private"] | ||||
| 	pastePassword, pastePasswordFound := params["paste-password"] | ||||
|  | ||||
| 	if privateCheckboxFound && privateCheckbox[0] == "on" || pastePasswordFound && pastePassword[0] != "" { | ||||
| 		paste.Private = true | ||||
| 	} | ||||
| @@ -118,7 +135,9 @@ func pastePOSTWebInterface(ec echo.Context) error { | ||||
| 	id, err2 := c.Database.SavePaste(paste) | ||||
| 	if err2 != nil { | ||||
| 		c.Logger.Error().Err(err2).Msg("Failed to save paste") | ||||
|  | ||||
| 		errtpl := templater.GetErrorTemplate(ec, "Failed to save paste. Please, try again later.") | ||||
|  | ||||
| 		return ec.HTML(http.StatusBadRequest, errtpl) | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -48,7 +48,9 @@ func pastesGET(ec echo.Context) error { | ||||
| 	} | ||||
|  | ||||
| 	pageFromParamRaw := ec.Param("page") | ||||
|  | ||||
| 	var page = 1 | ||||
|  | ||||
| 	if pageFromParamRaw != "" { | ||||
| 		pageRaw := regexInts.FindAllString(pageFromParamRaw, 1)[0] | ||||
| 		page, _ = strconv.Atoi(pageRaw) | ||||
| @@ -65,12 +67,15 @@ func pastesGET(ec echo.Context) error { | ||||
| 	// Show "No pastes to show" on any error for now. | ||||
| 	if err3 != nil { | ||||
| 		c.Logger.Error().Err(err3).Msg("Failed to get pastes list from database") | ||||
|  | ||||
| 		noPastesToShowTpl := templater.GetErrorTemplate(ec, "No pastes to show.") | ||||
|  | ||||
| 		return ec.HTML(http.StatusOK, noPastesToShowTpl) | ||||
| 	} | ||||
|  | ||||
| 	if len(pastes) > 0 { | ||||
| 		pastesString = "" | ||||
|  | ||||
| 		for i := range pastes { | ||||
| 			pasteDataMap := make(map[string]string) | ||||
| 			pasteDataMap["pasteID"] = strconv.Itoa(pastes[i].ID) | ||||
| @@ -79,7 +84,9 @@ func pastesGET(ec echo.Context) error { | ||||
|  | ||||
| 			// Get max 4 lines of each paste. | ||||
| 			pasteDataSplitted := strings.Split(pastes[i].Data, "\n") | ||||
|  | ||||
| 			var pasteData string | ||||
|  | ||||
| 			if len(pasteDataSplitted) < 4 { | ||||
| 				pasteData = pastes[i].Data | ||||
| 			} else { | ||||
| @@ -100,5 +107,5 @@ func pastesGET(ec echo.Context) error { | ||||
|  | ||||
| 	pasteListTpl := templater.GetTemplate(ec, "pastelist_list.html", map[string]string{"pastes": pastesString, "pagination": paginationHTML}) | ||||
|  | ||||
| 	return ec.HTML(http.StatusOK, string(pasteListTpl)) | ||||
| 	return ec.HTML(http.StatusOK, pasteListTpl) | ||||
| } | ||||
|   | ||||
| @@ -39,7 +39,7 @@ var ( | ||||
| 	log zerolog.Logger | ||||
| ) | ||||
|  | ||||
| // New initializes captcha package and adds neccessary HTTP and API | ||||
| // New initializes captcha package and adds necessary HTTP and API | ||||
| // endpoints. | ||||
| func New(cc *context.Context) { | ||||
| 	c = cc | ||||
| @@ -53,6 +53,7 @@ func New(cc *context.Context) { | ||||
| func NewCaptcha() string { | ||||
| 	s := captcha.New() | ||||
| 	log.Debug().Str("captcha string", s).Msg("Created new captcha string") | ||||
|  | ||||
| 	return s | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -24,8 +24,8 @@ | ||||
|  | ||||
| package config | ||||
|  | ||||
| // ConfigDatabase describes database configuration. | ||||
| type ConfigDatabase struct { | ||||
| // Database describes database configuration. | ||||
| type Database struct { | ||||
| 	Type     string `yaml:"type"` | ||||
| 	Path     string `yaml:"path"` | ||||
| 	Address  string `yaml:"address"` | ||||
|   | ||||
| @@ -24,8 +24,8 @@ | ||||
|  | ||||
| package config | ||||
|  | ||||
| // ConfigHTTP describes HTTP server configuration. | ||||
| type ConfigHTTP struct { | ||||
| // HTTP describes HTTP server configuration. | ||||
| type HTTP struct { | ||||
| 	Address       string `yaml:"address"` | ||||
| 	Port          string `yaml:"port"` | ||||
| 	AllowInsecure bool   `yaml:"allow_insecure"` | ||||
|   | ||||
| @@ -24,8 +24,8 @@ | ||||
|  | ||||
| package config | ||||
|  | ||||
| // ConfigLogging describes logger configuration. | ||||
| type ConfigLogging struct { | ||||
| // Logging describes logger configuration. | ||||
| type Logging struct { | ||||
| 	LogToFile bool   `yaml:"log_to_file"` | ||||
| 	FileName  string `yaml:"filename"` | ||||
| 	LogLevel  string `yaml:"loglevel"` | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
|  | ||||
| package config | ||||
|  | ||||
| // ConfigPastes describes pastes subsystem configuration. | ||||
| type ConfigPastes struct { | ||||
| // Pastes describes pastes subsystem configuration. | ||||
| type Pastes struct { | ||||
| 	Pagination int `yaml:"pagination"` | ||||
| } | ||||
|   | ||||
| @@ -24,10 +24,10 @@ | ||||
|  | ||||
| package config | ||||
|  | ||||
| // ConfigStruct describes whole configuration. | ||||
| type ConfigStruct struct { | ||||
| 	Database ConfigDatabase `yaml:"database"` | ||||
| 	Logging  ConfigLogging  `yaml:"logging"` | ||||
| 	HTTP     ConfigHTTP     `yaml:"http"` | ||||
| 	Pastes   ConfigPastes   `yaml:"pastes"` | ||||
| // Struct describes whole configuration. | ||||
| type Struct struct { | ||||
| 	Database Database `yaml:"database"` | ||||
| 	Logging  Logging  `yaml:"logging"` | ||||
| 	HTTP     HTTP     `yaml:"http"` | ||||
| 	Pastes   Pastes   `yaml:"pastes"` | ||||
| } | ||||
|   | ||||
| @@ -46,7 +46,7 @@ import ( | ||||
| // contains everything every part of application need, like configuration | ||||
| // access, logger, etc. | ||||
| type Context struct { | ||||
| 	Config   *config.ConfigStruct | ||||
| 	Config   *config.Struct | ||||
| 	Database databaseinterface.Interface | ||||
| 	Echo     *echo.Echo | ||||
| 	Flagger  *flagger.Flagger | ||||
| @@ -104,7 +104,7 @@ func (c *Context) LoadConfiguration() { | ||||
|  | ||||
| 	c.Logger.Debug().Msgf("Configuration file path: %s", configPath) | ||||
|  | ||||
| 	c.Config = &config.ConfigStruct{} | ||||
| 	c.Config = &config.Struct{} | ||||
|  | ||||
| 	// Read configuration file. | ||||
| 	fileData, err2 := ioutil.ReadFile(normalizedConfigPath) | ||||
|   | ||||
| @@ -15,6 +15,7 @@ import ( | ||||
| // Puts memory usage into log lines. | ||||
| func (c *Context) getMemoryUsage(e *zerolog.Event, level zerolog.Level, message string) { | ||||
| 	var m runtime.MemStats | ||||
|  | ||||
| 	runtime.ReadMemStats(&m) | ||||
|  | ||||
| 	e.Str("memalloc", fmt.Sprintf("%dMB", m.Alloc/1024/1024)) | ||||
| @@ -28,6 +29,7 @@ func (c *Context) initializeLogger() { | ||||
| 	output := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: false, TimeFormat: time.RFC3339} | ||||
| 	output.FormatLevel = func(i interface{}) string { | ||||
| 		var v string | ||||
|  | ||||
| 		if ii, ok := i.(string); ok { | ||||
| 			ii = strings.ToUpper(ii) | ||||
| 			switch ii { | ||||
| @@ -47,6 +49,7 @@ func (c *Context) initializeLogger() { | ||||
| 				v = ii | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return fmt.Sprintf("| %s |", v) | ||||
| 	} | ||||
|  | ||||
| @@ -59,6 +62,7 @@ func (c *Context) initializeLogger() { | ||||
| func (c *Context) initializeLoggerPost() { | ||||
| 	// Set log level. | ||||
| 	c.Logger.Info().Msgf("Setting logger level: %s", c.Config.Logging.LogLevel) | ||||
|  | ||||
| 	switch c.Config.Logging.LogLevel { | ||||
| 	case "DEBUG": | ||||
| 		zerolog.SetGlobalLevel(zerolog.DebugLevel) | ||||
|   | ||||
| @@ -30,7 +30,7 @@ import ( | ||||
|  | ||||
| 	// local | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/database/dialects/flatfiles" | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface" | ||||
| 	dialectinterface "go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface" | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/database/dialects/mysql" | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/database/dialects/postgresql" | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/structs" | ||||
|   | ||||
| @@ -27,7 +27,7 @@ package flatfiles | ||||
| import ( | ||||
| 	// local | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/context" | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface" | ||||
| 	dialectinterface "go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -38,5 +38,6 @@ var ( | ||||
| func New(cc *context.Context) { | ||||
| 	c = cc | ||||
| 	f = &FlatFiles{} | ||||
|  | ||||
| 	c.Database.RegisterDialect(dialectinterface.Interface(Handler{})) | ||||
| } | ||||
|   | ||||
| @@ -54,15 +54,18 @@ func (ff *FlatFiles) GetPaste(pasteID int) (*structs.Paste, error) { | ||||
| 	ff.writeMutex.Lock() | ||||
| 	pastePath := filepath.Join(ff.path, "pastes", strconv.Itoa(pasteID)+".json") | ||||
| 	c.Logger.Debug().Msgf("Trying to load paste data from '%s'...", pastePath) | ||||
|  | ||||
| 	pasteInBytes, err := ioutil.ReadFile(pastePath) | ||||
| 	if err != nil { | ||||
| 		c.Logger.Debug().Msgf("Failed to read paste from storage: %s", err.Error()) | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	c.Logger.Debug().Msgf("Loaded %d bytes: %s", len(pasteInBytes), string(pasteInBytes)) | ||||
| 	ff.writeMutex.Unlock() | ||||
|  | ||||
| 	paste := &structs.Paste{} | ||||
|  | ||||
| 	err = json.Unmarshal(pasteInBytes, paste) | ||||
| 	if err != nil { | ||||
| 		c.Logger.Error().Msgf("Failed to parse paste: %s", err.Error()) | ||||
| @@ -83,6 +86,7 @@ func (ff *FlatFiles) GetPagedPastes(page int) ([]structs.Paste, error) { | ||||
|  | ||||
| 	// Iteration one - get only public pastes. | ||||
| 	var publicPastes []*Index | ||||
|  | ||||
| 	for _, paste := range ff.pastesIndex { | ||||
| 		if !paste.Private { | ||||
| 			publicPastes = append(publicPastes, paste) | ||||
| @@ -92,7 +96,9 @@ func (ff *FlatFiles) GetPagedPastes(page int) ([]structs.Paste, error) { | ||||
| 	c.Logger.Debug().Msgf("%+v", publicPastes) | ||||
|  | ||||
| 	// Iteration two - get paginated pastes. | ||||
| 	// nolint | ||||
| 	var pastesData []structs.Paste | ||||
|  | ||||
| 	for idx, paste := range publicPastes { | ||||
| 		if len(pastesData) == c.Config.Pastes.Pagination { | ||||
| 			break | ||||
| @@ -107,10 +113,12 @@ func (ff *FlatFiles) GetPagedPastes(page int) ([]structs.Paste, error) { | ||||
| 			c.Logger.Debug().Msgf("Paste with index %d isn't in pagination query: too high index", idx) | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		c.Logger.Debug().Msgf("Getting paste data (ID: %d, index: %d)", paste.ID, idx) | ||||
|  | ||||
| 		// Get paste data. | ||||
| 		pasteData := &structs.Paste{} | ||||
|  | ||||
| 		pasteRawData, err := ioutil.ReadFile(filepath.Join(ff.path, "pastes", strconv.Itoa(paste.ID)+".json")) | ||||
| 		if err != nil { | ||||
| 			c.Logger.Error().Msgf("Failed to read paste data: %s", err.Error()) | ||||
| @@ -160,13 +168,16 @@ func (ff *FlatFiles) Initialize() { | ||||
| 		curUser, err := user.Current() | ||||
| 		if err != nil { | ||||
| 			c.Logger.Error().Msg("Failed to get current user. Will replace '~' for '/' in storage path!") | ||||
|  | ||||
| 			path = strings.Replace(path, "~", "/", -1) | ||||
| 		} | ||||
|  | ||||
| 		path = strings.Replace(path, "~", curUser.HomeDir, -1) | ||||
| 	} | ||||
|  | ||||
| 	path, _ = filepath.Abs(path) | ||||
| 	ff.path = path | ||||
|  | ||||
| 	c.Logger.Debug().Msgf("Storage path is now: %s", ff.path) | ||||
|  | ||||
| 	// Create directory if necessary. | ||||
| @@ -209,29 +220,35 @@ func (ff *FlatFiles) SavePaste(p *structs.Paste) (int64, error) { | ||||
| 	// Write paste data on disk. | ||||
| 	filesOnDisk, _ := ioutil.ReadDir(filepath.Join(ff.path, "pastes")) | ||||
| 	pasteID := len(filesOnDisk) + 1 | ||||
| 	c.Logger.Debug().Msgf("Writing paste to disk, ID will be " + strconv.Itoa(pasteID)) | ||||
| 	p.ID = pasteID | ||||
|  | ||||
| 	c.Logger.Debug().Msgf("Writing paste to disk, ID will be " + strconv.Itoa(pasteID)) | ||||
|  | ||||
| 	data, err := json.Marshal(p) | ||||
| 	if err != nil { | ||||
| 		ff.writeMutex.Unlock() | ||||
| 		return 0, err | ||||
| 	} | ||||
|  | ||||
| 	err = ioutil.WriteFile(filepath.Join(ff.path, "pastes", strconv.Itoa(pasteID)+".json"), data, 0644) | ||||
| 	if err != nil { | ||||
| 		ff.writeMutex.Unlock() | ||||
| 		return 0, err | ||||
| 	} | ||||
|  | ||||
| 	// Add it to cache. | ||||
| 	indexData := &Index{} | ||||
| 	indexData.ID = pasteID | ||||
| 	indexData.Private = p.Private | ||||
| 	ff.pastesIndex = append(ff.pastesIndex, indexData) | ||||
| 	ff.writeMutex.Unlock() | ||||
|  | ||||
| 	return int64(pasteID), nil | ||||
| } | ||||
|  | ||||
| func (ff *FlatFiles) Shutdown() { | ||||
| 	c.Logger.Info().Msg("Saving indexes...") | ||||
|  | ||||
| 	indexData, err := json.Marshal(ff.pastesIndex) | ||||
| 	if err != nil { | ||||
| 		c.Logger.Error().Msgf("Failed to encode index data into JSON: %s", err.Error()) | ||||
|   | ||||
| @@ -27,7 +27,7 @@ package mysql | ||||
| import ( | ||||
| 	// local | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/context" | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface" | ||||
| 	dialectinterface "go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -38,5 +38,6 @@ var ( | ||||
| func New(cc *context.Context) { | ||||
| 	c = cc | ||||
| 	d = &Database{} | ||||
|  | ||||
| 	c.Database.RegisterDialect(dialectinterface.Interface(Handler{})) | ||||
| } | ||||
|   | ||||
| @@ -30,6 +30,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| func InitialUp(tx *sql.Tx) error { | ||||
| 	// nolint | ||||
| 	_, err := tx.Exec("CREATE TABLE `pastes` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Paste ID', `title` text NOT NULL COMMENT 'Paste title', `data` longtext NOT NULL COMMENT 'Paste data', `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Paste creation timestamp', `keep_for` int(4) NOT NULL DEFAULT 1 COMMENT 'Keep for integer. 0 - forever.', `keep_for_unit_type` int(1) NOT NULL DEFAULT 1 COMMENT 'Keep for unit type. 1 - minutes, 2 - hours, 3 - days, 4 - months.', PRIMARY KEY (`id`), UNIQUE KEY `id` (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='Pastes';") | ||||
| 	if err != nil { | ||||
| 		return err | ||||
|   | ||||
| @@ -69,7 +69,9 @@ func (db *Database) GetDatabaseConnection() *sql.DB { | ||||
| // GetPaste returns a single paste by ID. | ||||
| func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) { | ||||
| 	db.check() | ||||
|  | ||||
| 	p := &structs.Paste{} | ||||
|  | ||||
| 	err := db.db.Get(p, db.db.Rebind("SELECT * FROM `pastes` WHERE id=?"), pasteID) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -80,8 +82,11 @@ func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) { | ||||
|  | ||||
| func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) { | ||||
| 	db.check() | ||||
| 	var pastesRaw []structs.Paste | ||||
| 	var pastes []structs.Paste | ||||
|  | ||||
| 	var ( | ||||
| 		pastesRaw []structs.Paste | ||||
| 		pastes    []structs.Paste | ||||
| 	) | ||||
|  | ||||
| 	// Pagination. | ||||
| 	var startPagination = 0 | ||||
| @@ -105,8 +110,12 @@ func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) { | ||||
|  | ||||
| func (db *Database) GetPastesPages() int { | ||||
| 	db.check() | ||||
| 	var pastesRaw []structs.Paste | ||||
| 	var pastes []structs.Paste | ||||
|  | ||||
| 	var ( | ||||
| 		pastesRaw []structs.Paste | ||||
| 		pastes    []structs.Paste | ||||
| 	) | ||||
|  | ||||
| 	err := db.db.Get(&pastesRaw, "SELECT * FROM `pastes` WHERE private != true") | ||||
| 	if err != nil { | ||||
| 		return 1 | ||||
| @@ -155,6 +164,7 @@ func (db *Database) Initialize() { | ||||
| 	_ = dbConn.MustExec("SET @@session.time_zone='+00:00';") | ||||
|  | ||||
| 	c.Logger.Info().Msg("Database connection established") | ||||
|  | ||||
| 	db.db = dbConn | ||||
|  | ||||
| 	// Perform migrations. | ||||
| @@ -164,6 +174,7 @@ func (db *Database) Initialize() { | ||||
|  | ||||
| func (db *Database) SavePaste(p *structs.Paste) (int64, error) { | ||||
| 	db.check() | ||||
|  | ||||
| 	result, err := db.db.NamedExec("INSERT INTO `pastes` (title, data, created_at, keep_for, keep_for_unit_type, language, private, password, password_salt) VALUES (:title, :data, :created_at, :keep_for, :keep_for_unit_type, :language, :private, :password, :password_salt)", p) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
|   | ||||
| @@ -27,7 +27,7 @@ package postgresql | ||||
| import ( | ||||
| 	// local | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/context" | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface" | ||||
| 	dialectinterface "go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -38,5 +38,6 @@ var ( | ||||
| func New(cc *context.Context) { | ||||
| 	c = cc | ||||
| 	d = &Database{} | ||||
|  | ||||
| 	c.Database.RegisterDialect(dialectinterface.Interface(Handler{})) | ||||
| } | ||||
|   | ||||
| @@ -36,6 +36,7 @@ import ( | ||||
|  | ||||
| 	// other | ||||
| 	"github.com/jmoiron/sqlx" | ||||
| 	// postgresql adapter | ||||
| 	_ "github.com/lib/pq" | ||||
| ) | ||||
|  | ||||
| @@ -70,7 +71,9 @@ func (db *Database) GetDatabaseConnection() *sql.DB { | ||||
| // GetPaste returns a single paste by ID. | ||||
| func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) { | ||||
| 	db.check() | ||||
|  | ||||
| 	p := &structs.Paste{} | ||||
|  | ||||
| 	err := db.db.Get(p, db.db.Rebind("SELECT * FROM pastes WHERE id=$1"), pasteID) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -88,8 +91,11 @@ func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) { | ||||
|  | ||||
| func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) { | ||||
| 	db.check() | ||||
| 	var pastesRaw []structs.Paste | ||||
| 	var pastes []structs.Paste | ||||
|  | ||||
| 	var ( | ||||
| 		pastesRaw []structs.Paste | ||||
| 		pastes    []structs.Paste | ||||
| 	) | ||||
|  | ||||
| 	// Pagination. | ||||
| 	var startPagination = 0 | ||||
| @@ -119,8 +125,12 @@ func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) { | ||||
|  | ||||
| func (db *Database) GetPastesPages() int { | ||||
| 	db.check() | ||||
| 	var pastesRaw []structs.Paste | ||||
| 	var pastes []structs.Paste | ||||
|  | ||||
| 	var ( | ||||
| 		pastesRaw []structs.Paste | ||||
| 		pastes    []structs.Paste | ||||
| 	) | ||||
|  | ||||
| 	err := db.db.Get(&pastesRaw, "SELECT * FROM pastes WHERE private != true") | ||||
| 	if err != nil { | ||||
| 		return 1 | ||||
| @@ -164,6 +174,7 @@ func (db *Database) Initialize() { | ||||
| 	} | ||||
|  | ||||
| 	c.Logger.Info().Msg("Database connection established") | ||||
|  | ||||
| 	db.db = dbConn | ||||
|  | ||||
| 	// Perform migrations. | ||||
| @@ -173,12 +184,14 @@ func (db *Database) Initialize() { | ||||
|  | ||||
| func (db *Database) SavePaste(p *structs.Paste) (int64, error) { | ||||
| 	db.check() | ||||
|  | ||||
| 	stmt, err := db.db.PrepareNamed("INSERT INTO pastes (title, data, created_at, keep_for, keep_for_unit_type, language, private, password, password_salt) VALUES (:title, :data, :created_at, :keep_for, :keep_for_unit_type, :language, :private, :password, :password_salt) RETURNING id") | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
|  | ||||
| 	var id int64 | ||||
|  | ||||
| 	err = stmt.Get(&id, p) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
|   | ||||
| @@ -27,7 +27,7 @@ package database | ||||
| import ( | ||||
| 	// local | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/context" | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/database/interface" | ||||
| 	databaseinterface "go.dev.pztrn.name/fastpastebin/internal/database/interface" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -39,5 +39,6 @@ var ( | ||||
| func New(cc *context.Context) { | ||||
| 	c = cc | ||||
| 	d = &Database{} | ||||
|  | ||||
| 	c.RegisterDatabaseInterface(databaseinterface.Interface(Handler{})) | ||||
| } | ||||
|   | ||||
| @@ -29,7 +29,8 @@ import ( | ||||
| 	"database/sql" | ||||
|  | ||||
| 	// local | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface" | ||||
|  | ||||
| 	dialectinterface "go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface" | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/structs" | ||||
| ) | ||||
|  | ||||
|   | ||||
| @@ -29,7 +29,7 @@ import ( | ||||
| 	"database/sql" | ||||
|  | ||||
| 	// local | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface" | ||||
| 	dialectinterface "go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface" | ||||
| 	"go.dev.pztrn.name/fastpastebin/internal/structs" | ||||
| ) | ||||
|  | ||||
|   | ||||
| @@ -10,6 +10,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| // CreateHTML creates pagination HTML based on passed parameters. | ||||
| // nolint | ||||
| func CreateHTML(currentPage int, pages int, linksBase string) string { | ||||
| 	// Load templates. | ||||
| 	paginationHTMLRaw, err := static.ReadFile("pagination.html") | ||||
| @@ -38,12 +39,15 @@ func CreateHTML(currentPage int, pages int, linksBase string) string { | ||||
| 		paginationString = strings.Replace(string(paginationLinkCurrentRaw), "{pageNum}", strconv.Itoa(currentPage), -1) | ||||
| 	} else { | ||||
| 		paginationString = strings.Replace(string(paginationLinkRaw), "{pageNum}", "1", -1) | ||||
| 		paginationString = strings.Replace(string(paginationString), "{paginationLink}", linksBase+"1", -1) | ||||
| 		paginationString = strings.Replace(paginationString, "{paginationLink}", linksBase+"1", -1) | ||||
| 	} | ||||
|  | ||||
| 	var ellipsisStartAdded = false | ||||
| 	var ellipsisEndAdded = false | ||||
| 	i := 2 | ||||
| 	var ( | ||||
| 		ellipsisStartAdded = false | ||||
| 		ellipsisEndAdded   = false | ||||
| 		i                  = 2 | ||||
| 	) | ||||
|  | ||||
| 	for i <= pages { | ||||
| 		if pages > 5 { | ||||
| 			if currentPage-3 < i && currentPage+3 > i || i == pages { | ||||
|   | ||||
| @@ -36,22 +36,22 @@ import ( | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	PASTE_KEEP_FOREVER     = 0 | ||||
| 	PASTE_KEEP_FOR_MINUTES = 1 | ||||
| 	PASTE_KEEP_FOR_HOURS   = 2 | ||||
| 	PASTE_KEEP_FOR_DAYS    = 3 | ||||
| 	PASTE_KEEP_FOR_MONTHS  = 4 | ||||
| 	PasteKeepForever    = 0 | ||||
| 	PasteKeepForMinutes = 1 | ||||
| 	PasteKeepForHours   = 2 | ||||
| 	PasteKeepForDays    = 3 | ||||
| 	PasteKeepForMonths  = 4 | ||||
|  | ||||
| 	charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	PASTE_KEEPS_CORELLATION = map[string]int{ | ||||
| 		"M":       PASTE_KEEP_FOR_MINUTES, | ||||
| 		"h":       PASTE_KEEP_FOR_HOURS, | ||||
| 		"d":       PASTE_KEEP_FOR_DAYS, | ||||
| 		"m":       PASTE_KEEP_FOR_MONTHS, | ||||
| 		"forever": PASTE_KEEP_FOREVER, | ||||
| 	PasteKeepsCorellation = map[string]int{ | ||||
| 		"M":       PasteKeepForMinutes, | ||||
| 		"h":       PasteKeepForHours, | ||||
| 		"d":       PasteKeepForDays, | ||||
| 		"m":       PasteKeepForMonths, | ||||
| 		"forever": PasteKeepForever, | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| @@ -74,6 +74,7 @@ func (p *Paste) CreatePassword(password string) error { | ||||
| 	// Create salt - random string. | ||||
| 	seededRand := rand.New(rand.NewSource(time.Now().UnixNano())) | ||||
| 	saltBytes := make([]byte, 64) | ||||
|  | ||||
| 	for i := range saltBytes { | ||||
| 		saltBytes[i] = charset[seededRand.Intn(len(charset))] | ||||
| 	} | ||||
| @@ -86,6 +87,7 @@ func (p *Paste) CreatePassword(password string) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	passwordHashBytes := sha256.Sum256(passwordCrypted) | ||||
| 	p.Password = fmt.Sprintf("%x", passwordHashBytes) | ||||
|  | ||||
| @@ -100,16 +102,17 @@ func (p *Paste) GenerateCryptedCookieValue() string { | ||||
|  | ||||
| func (p *Paste) GetExpirationTime() time.Time { | ||||
| 	var expirationTime time.Time | ||||
|  | ||||
| 	switch p.KeepForUnitType { | ||||
| 	case PASTE_KEEP_FOREVER: | ||||
| 	case PasteKeepForever: | ||||
| 		expirationTime = time.Now().UTC().Add(time.Hour * 1) | ||||
| 	case PASTE_KEEP_FOR_MINUTES: | ||||
| 	case PasteKeepForMinutes: | ||||
| 		expirationTime = p.CreatedAt.Add(time.Minute * time.Duration(p.KeepFor)) | ||||
| 	case PASTE_KEEP_FOR_HOURS: | ||||
| 	case PasteKeepForHours: | ||||
| 		expirationTime = p.CreatedAt.Add(time.Hour * time.Duration(p.KeepFor)) | ||||
| 	case PASTE_KEEP_FOR_DAYS: | ||||
| 	case PasteKeepForDays: | ||||
| 		expirationTime = p.CreatedAt.Add(time.Hour * 24 * time.Duration(p.KeepFor)) | ||||
| 	case PASTE_KEEP_FOR_MONTHS: | ||||
| 	case PasteKeepForMonths: | ||||
| 		expirationTime = p.CreatedAt.Add(time.Hour * 24 * 30 * time.Duration(p.KeepFor)) | ||||
| 	} | ||||
|  | ||||
| @@ -121,11 +124,7 @@ func (p *Paste) IsExpired() bool { | ||||
| 	curTime := time.Now().UTC() | ||||
| 	expirationTime := p.GetExpirationTime() | ||||
|  | ||||
| 	if curTime.Sub(expirationTime).Seconds() > 0 { | ||||
| 		return true | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| 	return curTime.Sub(expirationTime).Seconds() > 0 | ||||
| } | ||||
|  | ||||
| // VerifyPassword verifies that provided password is valid. | ||||
| @@ -135,12 +134,9 @@ func (p *Paste) VerifyPassword(password string) bool { | ||||
| 	if err != nil { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	passwordHashBytes := sha256.Sum256(passwordCrypted) | ||||
| 	providedPassword := fmt.Sprintf("%x", passwordHashBytes) | ||||
|  | ||||
| 	if providedPassword == p.Password { | ||||
| 		return true | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| 	return providedPassword == p.Password | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user