14 Commits

Author SHA1 Message Date
74ea9b6863 Prepare to release 0.4.1.
All checks were successful
continuous-integration/drone/push Build is passing
2022-08-14 16:26:11 +05:00
30f8b4975c Get rid of flagger.
All checks were successful
continuous-integration/drone/push Build is passing
2022-08-14 16:20:16 +05:00
dcd361de1f Update dependencies, fix footer link.
All checks were successful
continuous-integration/drone/push Build is passing
2022-08-14 16:02:16 +05:00
2ec0e28243 Make linter happy and move to os from io/ioutil for reading/writing.
All checks were successful
continuous-integration/drone/push Build is passing
2022-08-14 15:49:05 +05:00
df5671586e Update images used for building containers and code test/lint, fill CHANGELOG.
Some checks failed
continuous-integration/drone/push Build is failing
2022-08-14 15:34:47 +05:00
59dafc373f Update chroma to 2.2.0, line number links appeared.
Some checks failed
continuous-integration/drone/push Build is failing
2022-08-14 14:57:54 +05:00
25489dc103 Forgotten files for previous commit.
Some checks failed
continuous-integration/drone/push Build is failing
2022-08-14 14:49:31 +05:00
1dc6dfe00e Update README and mention where bugreporting should take place.
Some checks failed
continuous-integration/drone/push Build is failing
Also added markdownlint configuration.
2022-08-14 14:47:28 +05:00
02e933efed Use mirrorred images in Dockerfile.
All checks were successful
continuous-integration/drone/push Build is passing
2022-06-28 22:19:42 +05:00
d2b3304a5a As it isn't Drone official plugins now, containers with dind should be privileged.
Some checks failed
continuous-integration/drone/push Build is failing
2022-06-28 21:44:23 +05:00
9164c53c54 Force docker plugin version.
Some checks failed
continuous-integration/drone/push Build is failing
2022-06-28 21:38:09 +05:00
18734ebd18 Switch to mirrorred images for Drone CI.
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2022-06-28 21:19:35 +05:00
6b04a1dcd5 Update Dockerfile to use latest versions of Golang and Alpine.
All checks were successful
continuous-integration/drone/push Build is passing
2022-06-26 22:52:50 +05:00
1cb93c7d97 Update Drone configuration.
All checks were successful
continuous-integration/drone/push Build is passing
2022-06-26 22:49:37 +05:00
44 changed files with 247 additions and 289 deletions

View File

@@ -5,14 +5,16 @@ name: lint and test
steps:
- name: lint
image: golangci/golangci-lint:v1.46.2
image: code.pztrn.name/containers/mirror/golangci/golangci-lint:v1.48.0
pull: if-not-exists
environment:
CGO_ENABLED: 0
commands:
- golangci-lint run
- name: test
image: golang:1.18.3-alpine
image: code.pztrn.name/containers/mirror/golang:1.19.0-alpine
pull: if-not-exists
environment:
CGO_ENABLED: 0
commands:
@@ -28,7 +30,9 @@ depends_on:
steps:
- name: build master image
image: plugins/docker
image: code.pztrn.name/containers/mirror/plugins/docker:20.13.0
pull: if-not-exists
privileged: true
when:
branch: ["master"]
settings:
@@ -36,11 +40,13 @@ steps:
username: drone
password:
from_secret: drone_secret
repo: code.pztrn.name/pztrn/fastpastebin
repo: code.pztrn.name/apps/fastpastebin
auto_tag: true
- name: build tagged image
image: plugins/docker
image: code.pztrn.name/containers/mirror/plugins/docker:20.13.0
pull: if-not-exists
privileged: true
when:
event: ["tag"]
settings:
@@ -48,5 +54,5 @@ steps:
username: drone
password:
from_secret: drone_secret
repo: code.pztrn.name/pztrn/fastpastebin
repo: code.pztrn.name/apps/fastpastebin
auto_tag: true

5
.markdownlint.json Normal file
View File

@@ -0,0 +1,5 @@
{
"line-length": false,
"first-line-h1": false,
"no-duplicate-header": false
}

View File

@@ -1,12 +1,84 @@
# Changelog
``[A]`` - added
``[F]`` - fixed
``[R]`` - removed
All notable changes to this project will be documented in this file.
---
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 0.1.0
## [Unreleased]
## [0.4.1] - 2022-08-14
### Changed
* Update docker images - alpine to 3.16.1, golang to 1.19, golangci-lint to 1.48.0.
* Update chroma to v2.2.0.
* Update bulma to 0.9.4.
* Update bulma-tooltip to 1.2 (was 3.0.0, but repo was switched to CreativeBulma).
* Update github.com/dchest/captcha to v1.0.0.
### Fixed
* Put valid repository's link in footer.
### Removed
* Removed `flagger` dependency.
## [0.4.0] - 2021-01-09
### Added
* PostgreSQL support.
* Docker containerization for every commit and tag.
* Pastes cleanup procedure.
### Changed
* Updated bulma to v 0.7.5.
* Moved from `io/ioutil` to `os` package for reading/writing files and directories.
### Fixed
* Dirty hack to get database connection reestablish (for sure).
## 0.3.0
Release changelogs lost :(.
## [0.2.0] - 2018-05-27
### Added
* Possibility to create different database backends. Currently `mysql` and `flatfiles` are available.
### Changed
* De-hardcoded pagination configuration, it is now configurable via configuration file.
## [0.1.1] - 2018-05-26
### Added
* Footer copyrights.
### Changed
* Refactored templates: now they're included in each other if neccessary.
### Fixed
* Fixed nasty bugs with private pastes that causing fastpastebin to crash.
* Logger level from configuration now properly set.
## [0.1.0] - 2018-05-19
First normal release. Fast Paste Bin is able to handle public, private
and passworded pastes.
and passworded pastes.
[Unreleased]: https://code.pztrn.name/apps/fastpastebin/compare/v0.4.1...HEAD
[0.4.1]: https://code.pztrn.name/apps/fastpastebin/compare/0.4.0...v0.4.1
[0.4.0]: https://code.pztrn.name/apps/fastpastebin/compare/v0.2.0...0.4.0
[0.2.0]: https://code.pztrn.name/apps/fastpastebin/compare/v0.1.1...v0.2.0
[0.1.1]: https://code.pztrn.name/apps/fastpastebin/compare/v0.1.0...v0.1.1
[0.1.0]: https://code.pztrn.name/apps/fastpastebin/src/tag/v0.1.0

View File

@@ -1,4 +1,4 @@
FROM golang:1.16.5-alpine AS build
FROM code.pztrn.name/containers/mirror/golang:1.19.0-alpine AS build
WORKDIR /fastpastebin
COPY . .
@@ -7,7 +7,7 @@ WORKDIR /fastpastebin/cmd/fastpastebin
RUN CGO_ENABLED=0 go build -tags netgo
FROM alpine:3.13
FROM code.pztrn.name/containers/mirror/alpine:3.16.1
LABEL maintainer "Stanislav N. <pztrn@pztrn.name>"
COPY --from=build /fastpastebin/cmd/fastpastebin/fastpastebin /app/fastpastebin

View File

@@ -1,9 +1,11 @@
# Fast Pastebin
[![Build Status](https://github-ci.pztrn.name/api/badges/pztrn/fastpastebin/status.svg)](https://github-ci.pztrn.name/pztrn/fastpastebin) ![Keybase XLM](https://img.shields.io/keybase/xlm/pztrn)
[![Build Status](https://ci.code.pztrn.name/api/badges/apps/fastpastebin/status.svg)](https://ci.code.pztrn.name/apps/fastpastebin)
Easy-to-use-and-install pastebin software written in Go. No bells or whistles, no websockets and even NO JAVASCRIPT!
**Please, use [my gitea](https://code.pztrn.name/apps/fastpastebin) for bug reporting. All other places are mirrors!**
## Current functionality
* Create and view public and private pastes.
@@ -14,14 +16,14 @@ Easy-to-use-and-install pastebin software written in Go. No bells or whistles, n
## Caveats
* No links at lines numbers. See [this Chroma bug](https://github.com/alecthomas/chroma/issues/132)
* Not known at this moment.
## Installation and updating
Just issue:
```bash
CGO_ENABLED=0 go get -u -v go.dev.pztrn.name/fastpastebin/cmd/fastpastebin
CGO_ENABLED=0 go install go.dev.pztrn.name/fastpastebin/cmd/fastpastebin@latest
```
This command can be used to update Fast Paste Bin.
@@ -34,18 +36,13 @@ Configuration file position is irrelevant, there is no hardcoded paths where Fas
## Developing
Developers should install [fileb0x](https://github.com/UnnoTed/fileb0x/) which is used as replacement to go-bindata for embedding assets into binary. After changing assets they should be recompiled into Go code. At repository root execute this command and you'll be fine:
Use linters, formatters, etc. VSCode with Go plugin is recommended for developing as it will perform most of linting-formatting
actions automagically.
```bash
fileb0x fileb0x.yml
```
Also, Sublime Text with LSP-gopls will also work just fine.
Also if you're changed list of assets (by creating or deleting them) be sure to fix files list in ``fileb0x.yml`` file!
Try to follow [Go's code review comments](https://github.com/golang/go/wiki/CodeReviewComments) with few exceptions:
The rest is default - use linters, formatters, etc. VSCode with Go plugin is recommended for developing as it will perform most of linting-formatting
actions automagically. Try to follow [Go's code review comments](https://github.com/golang/go/wiki/CodeReviewComments) with few exceptions:
* Imports should be organized in 3 groups: stdlib, local, other. See [this file](https://sources.dev.pztrn.name/fastpastebin/fastpastebin/src/branch/master/domains/pastes/paste_get.go) for example.
* We're not forcing any limits on line length for code, only for comments, they should be 72-76 chars long.
## ToDo

View File

@@ -1,3 +1,4 @@
//nolint:gofmt,gofumpt,goimports
package assets
import "embed"

View File

@@ -5,7 +5,7 @@
<strong>{version}</strong> by
<a href="https://pztrn.name">Stanislav N. aka pztrn</a>. The source code is licensed
<a href="http://opensource.org/licenses/mit-license.php">MIT</a>. Get
<a href="https://gitlab.pztrn.name/fastpastebin/fastpastebin">source or binary releases here</a>!
<a href="https://code.pztrn.name/apps/fastpastebin">source or binary releases here</a>!
</p>
</div>
</div>

View File

@@ -38,13 +38,13 @@
</div>
</div>
</div>
<div class="field tooltip is-tooltip-bottom is-tooltip-multiline" data-tooltip="Should this paste be accessible only with special URL and not shown in pastes list? WARNING: If you'll enter password into 'Password for paste' field this checkbox will be assumed as checked!">
<div class="field tooltip is-tooltip-bottom is-tooltip-multiline has-tooltip-arrow" data-tooltip="Should this paste be accessible only with special URL and not shown in pastes list? WARNING: If you'll enter password into 'Password for paste' field this checkbox will be assumed as checked!">
<label class="checkbox">
<input type="checkbox" name="paste-private" id="paste-private"> Private paste with unique URL?
</label>
</div>
<div>OR</div>
<div class="field tooltip is-tooltip-bottom is-tooltip-multiline" data-tooltip="If you'll enter password here - 'Private paste with unique URL' checkbox will be assumed as checked.">
<div class="field tooltip is-tooltip-bottom is-tooltip-multiline has-tooltip-arrow" data-tooltip="If you'll enter password here - 'Private paste with unique URL' checkbox will be assumed as checked.">
<label for="paste-password">Password for paste:</label>
<div class="control">
<input class="input" type="text" placeholder="Enter password." name="paste-password" id="paste-password">
@@ -78,4 +78,4 @@
</div>
</div>
</form>
</section>
</section>

View File

@@ -5,8 +5,8 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Fast Paste Bin</title>
<link rel="stylesheet" href="/static/css/bulma-0.7.5.min.css">
<link rel="stylesheet" href="/static/css/bulma-tooltip-3.0.0.min.css">
<link rel="stylesheet" href="/static/css/bulma-0.9.4.min.css">
<link rel="stylesheet" href="/static/css/bulma-tooltip-1.2.min.css">
<link rel="stylesheet" href="/static/css/style.css">
</head>
@@ -17,4 +17,4 @@
{footer}
</footer>
</html>
</html>

File diff suppressed because one or more lines are too long

1
assets/static/css/bulma-0.9.4.min.css vendored Normal file

File diff suppressed because one or more lines are too long

2
assets/static/css/bulma-tooltip-1.2.min.css vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -25,6 +25,7 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
@@ -48,7 +49,7 @@ func main() {
// to be added.
// Parse flags.
appCtx.Flagger.Parse()
flag.Parse()
// Continue loading.
appCtx.LoadConfiguration()

View File

@@ -35,11 +35,11 @@ import (
func dbNotAvailableGet(ec echo.Context) error {
htmlData := templater.GetTemplate(ec, "database_not_available.html", nil)
// nolint:wrapcheck
//nolint:wrapcheck
return ec.HTML(http.StatusInternalServerError, htmlData)
}
func dbNotAvailableRawGet(ec echo.Context) error {
// nolint:wrapcheck
//nolint:wrapcheck
return ec.String(http.StatusInternalServerError, "Database not available\nSomething went wrong while trying to connect to database. Check logs for details.")
}

View File

@@ -27,7 +27,7 @@ package indexpage
import (
"net/http"
"github.com/alecthomas/chroma/lexers"
"github.com/alecthomas/chroma/v2/lexers"
"github.com/labstack/echo"
"go.dev.pztrn.name/fastpastebin/internal/captcha"
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/flatfiles"
@@ -39,7 +39,7 @@ func indexGet(ectx echo.Context) error {
// We should check if database connection available.
dbConn := ctx.Database.GetDatabaseConnection()
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.Redirect(http.StatusFound, "/database_not_available")
}
@@ -56,6 +56,6 @@ func indexGet(ectx echo.Context) error {
htmlData := templater.GetTemplate(ectx, "index.html", map[string]string{"lexers": availableLexersSelectOpts, "captchaString": captchaString})
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusOK, htmlData)
}

View File

@@ -6,10 +6,9 @@ import (
"strconv"
"time"
"github.com/alecthomas/chroma"
htmlfmt "github.com/alecthomas/chroma/formatters/html"
"github.com/alecthomas/chroma/lexers"
"github.com/alecthomas/chroma/styles"
htmlfmt "github.com/alecthomas/chroma/v2/formatters/html"
"github.com/alecthomas/chroma/v2/lexers"
"github.com/alecthomas/chroma/v2/styles"
"github.com/labstack/echo"
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/flatfiles"
"go.dev.pztrn.name/fastpastebin/internal/structs"
@@ -93,7 +92,7 @@ func pasteGETWebInterface(ectx echo.Context) error {
errtpl := templater.GetErrorTemplate(ectx, "Paste #"+pasteIDStr+" not found")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusBadRequest, errtpl)
}
@@ -115,7 +114,7 @@ func pasteGETWebInterface(ectx echo.Context) error {
if err == pasteExpired || err == pasteNotFound || err == pasteTimestampInvalid {
errtpl := templater.GetErrorTemplate(ectx, "Paste #"+pasteIDRaw+" not found")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusNotFound, errtpl)
}
@@ -124,7 +123,7 @@ func pasteGETWebInterface(ectx echo.Context) error {
if err == pasteCookieInvalid {
ctx.Logger.Info().Int("paste ID", pasteID).Msg("Invalid cookie, redirecting to auth page")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.Redirect(http.StatusMovedPermanently, "/paste/"+pasteIDStr+"/"+ectx.Param("timestamp")+"/verify")
}
@@ -167,7 +166,7 @@ func pasteGETWebInterface(ectx echo.Context) error {
style = styles.Fallback
}
// Get HTML formatter.
formatter := chroma.Formatter(htmlfmt.New(htmlfmt.WithLineNumbers(true), htmlfmt.LineNumbersInTable(true), htmlfmt.LinkableLineNumbers(true, "L")))
formatter := htmlfmt.New(htmlfmt.WithLineNumbers(true), htmlfmt.LineNumbersInTable(true), htmlfmt.LinkableLineNumbers(true, "L"))
// Create buffer and format into it.
buf := new(bytes.Buffer)
@@ -182,7 +181,7 @@ func pasteGETWebInterface(ectx echo.Context) error {
// Get template and format it.
pasteHTML := templater.GetTemplate(ectx, "paste.html", pasteData)
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusOK, pasteHTML)
}
@@ -201,7 +200,7 @@ func pastePasswordedVerifyGet(ectx echo.Context) error {
errtpl := templater.GetErrorTemplate(ectx, "Paste #"+pasteIDRaw+" not found")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusBadRequest, errtpl)
}
@@ -217,7 +216,7 @@ func pastePasswordedVerifyGet(ectx echo.Context) error {
if cookieValue == cookie.Value {
ctx.Logger.Info().Msg("Valid cookie, redirecting to paste page...")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.Redirect(http.StatusMovedPermanently, "/paste/"+pasteIDRaw+"/"+ectx.Param("timestamp"))
}
@@ -231,7 +230,7 @@ func pastePasswordedVerifyGet(ectx echo.Context) error {
verifyHTML := templater.GetTemplate(ectx, "passworded_paste_verify.html", htmlData)
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusOK, verifyHTML)
}
@@ -241,7 +240,7 @@ func pastePasswordedVerifyPost(ectx echo.Context) error {
dbConn := ctx.Database.GetDatabaseConnection()
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.Redirect(http.StatusFound, "/database_not_available")
}
@@ -258,7 +257,7 @@ func pastePasswordedVerifyPost(ectx echo.Context) error {
ctx.Logger.Error().Err(err1).Int("paste ID", pasteID).Msg("Failed to get paste")
errtpl := templater.GetErrorTemplate(ectx, "Paste #"+strconv.Itoa(pasteID)+" not found")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusBadRequest, errtpl)
}
@@ -268,7 +267,7 @@ func pastePasswordedVerifyPost(ectx echo.Context) error {
errtpl := templater.GetErrorTemplate(ectx, "Paste #"+strconv.Itoa(pasteID)+" not found")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusBadRequest, errtpl)
}
@@ -281,13 +280,13 @@ func pastePasswordedVerifyPost(ectx echo.Context) error {
cookie.Expires = time.Now().Add(24 * time.Hour)
ectx.SetCookie(cookie)
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.Redirect(http.StatusFound, "/paste/"+strconv.Itoa(pasteID)+"/"+timestampRaw)
}
errtpl := templater.GetErrorTemplate(ectx, "Invalid password. Please, try again.")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusBadRequest, errtpl)
}
@@ -297,7 +296,7 @@ func pasteRawGETWebInterface(ectx echo.Context) error {
// We should check if database connection available.
dbConn := ctx.Database.GetDatabaseConnection()
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.Redirect(http.StatusFound, "/database_not_available/raw")
}
@@ -312,14 +311,14 @@ func pasteRawGETWebInterface(ectx echo.Context) error {
if err1 != nil {
ctx.Logger.Error().Err(err1).Int("paste ID", pasteID).Msg("Failed to get paste from database")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusBadRequest, "Paste #"+pasteIDRaw+" does not exist.")
}
if paste.IsExpired() {
ctx.Logger.Error().Int("paste ID", pasteID).Msg("Paste is expired")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusBadRequest, "Paste #"+pasteIDRaw+" does not exist.")
}
@@ -331,7 +330,7 @@ func pasteRawGETWebInterface(ectx echo.Context) error {
if err2 != nil {
ctx.Logger.Error().Err(err2).Int("paste ID", pasteID).Str("provided timestamp", tsProvidedStr).Msg("Invalid timestamp provided for getting private paste")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found")
}
@@ -339,12 +338,12 @@ func pasteRawGETWebInterface(ectx echo.Context) error {
if tsProvided != pasteTS {
ctx.Logger.Error().Int("paste ID", pasteID).Int64("provided timestamp", tsProvided).Int64("paste timestamp", pasteTS).Msg("Incorrect timestamp provided for private paste")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found")
}
}
// nolint
//nolint
// ToDo: figure out how to handle passworded pastes here.
// Return error for now.
if paste.Password != "" {
@@ -352,6 +351,6 @@ func pasteRawGETWebInterface(ectx echo.Context) error {
return ectx.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found")
}
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.String(http.StatusOK, paste.Data)
}

View File

@@ -7,7 +7,7 @@ import (
"strings"
"time"
"github.com/alecthomas/chroma/lexers"
"github.com/alecthomas/chroma/v2/lexers"
"github.com/labstack/echo"
"go.dev.pztrn.name/fastpastebin/internal/captcha"
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/flatfiles"
@@ -24,7 +24,7 @@ func pastePOSTWebInterface(ectx echo.Context) error {
// We should check if database connection available.
dbConn := ctx.Database.GetDatabaseConnection()
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.Redirect(http.StatusFound, "/database_not_available")
}
@@ -34,7 +34,7 @@ func pastePOSTWebInterface(ectx echo.Context) error {
errtpl := templater.GetErrorTemplate(ectx, "Cannot create empty paste")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusBadRequest, errtpl)
}
@@ -46,7 +46,7 @@ func pastePOSTWebInterface(ectx echo.Context) error {
errtpl := templater.GetErrorTemplate(ectx, "Empty pastes aren't allowed.")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusBadRequest, errtpl)
}
@@ -55,7 +55,7 @@ func pastePOSTWebInterface(ectx echo.Context) error {
errtpl := templater.GetErrorTemplate(ectx, "Invalid 'Paste should be available for' parameter passed. Please do not try to hack us ;).")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusBadRequest, errtpl)
}
@@ -65,11 +65,11 @@ func pastePOSTWebInterface(ectx echo.Context) error {
errtpl := templater.GetErrorTemplate(ectx, "Invalid captcha solution.")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusBadRequest, errtpl)
}
// nolint:exhaustruct
//nolint:exhaustruct
paste := &structs.Paste{
Title: params["paste-title"][0],
Data: params["paste-contents"][0],
@@ -103,7 +103,7 @@ func pastePOSTWebInterface(ectx echo.Context) error {
errtpl := templater.GetErrorTemplate(ectx, "Invalid 'Paste should be available for' parameter passed. Please do not try to hack us ;).")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusBadRequest, errtpl)
}
}
@@ -144,7 +144,7 @@ func pastePOSTWebInterface(ectx echo.Context) error {
errtpl := templater.GetErrorTemplate(ectx, "Failed to save paste. Please, try again later.")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusBadRequest, errtpl)
}
@@ -153,10 +153,10 @@ func pastePOSTWebInterface(ectx echo.Context) error {
// Private pastes have it's timestamp in URL.
if paste.Private {
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.Redirect(http.StatusFound, "/paste/"+newPasteIDAsString+"/"+strconv.FormatInt(paste.CreatedAt.Unix(), 10))
}
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.Redirect(http.StatusFound, "/paste/"+newPasteIDAsString)
}

View File

@@ -41,7 +41,7 @@ func pastesGET(ectx echo.Context) error {
// We should check if database connection available.
dbConn := ctx.Database.GetDatabaseConnection()
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.Redirect(http.StatusFound, "/database_not_available")
}
@@ -68,7 +68,7 @@ func pastesGET(ectx echo.Context) error {
noPastesToShowTpl := templater.GetErrorTemplate(ectx, "No pastes to show.")
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusOK, noPastesToShowTpl)
}
@@ -106,6 +106,6 @@ func pastesGET(ectx echo.Context) error {
pasteListTpl := templater.GetTemplate(ectx, "pastelist_list.html", map[string]string{"pastes": pastesString, "pagination": paginationHTML})
// nolint:wrapcheck
//nolint:wrapcheck
return ectx.HTML(http.StatusOK, pasteListTpl)
}

View File

@@ -1,112 +0,0 @@
# all folders and files are relative to the path
# where fileb0x was run at!
# default: main
pkg: static
# destination
dest: "./assets/static/"
# gofmt
# type: bool
# default: false
fmt: false
# compress files
# at the moment, only supports gzip
#
# type: object
compression:
# activates the compression
#
# type: bool
# default: false
compress: false
# valid values are:
# -> "NoCompression"
# -> "BestSpeed"
# -> "BestCompression"
# -> "DefaultCompression" or ""
#
# type: string
# default: "DefaultCompression" # when: Compress == true && Method == ""
method: ""
# true = do it yourself (the file is written as gzip compressed file into the memory file system)
# false = decompress files at run time (while writing file into memory file system)
#
# type: bool
# default: false
keep: false
# ---------------
# -- DANGEROUS --
# ---------------
#
# cleans the destination folder (only b0xfiles)
# you should use this when using the spread function
# type: bool
# default: false
clean: true
# default: ab0x.go
output: "ab0x.go"
# [unexporTed] builds non-exporTed functions, variables and types...
# type: bool
# default: false
unexporTed: false
# [spread] means it will make a file to hold all fileb0x data
# and each file into a separaTed .go file
#
# example:
# theres 2 files in the folder assets, they're: hello.json and world.txt
# when spread is activaTed, fileb0x will make a file:
# b0x.go or [output]'s data, assets_hello.json.go and assets_world.txt.go
#
#
# type: bool
# default: false
spread: true
# [lcf] log changed files when spread is active
lcf: true
# type: array of objects
custom:
# type: array of strings
- files:
- "assets/css/bulma-0.7.5.min.css"
- "assets/css/bulma-tooltip-3.0.0.min.css"
- "assets/css/bulma.css.map"
- "assets/css/style.css"
- "assets/js/fontawesome-5.0.7.js"
# base is the path that will be removed from all files' path
# type: string
base: "assets"
# prefix is the path that will be added to all files' path
# type: string
prefix: "static/"
# end: files
- files:
- "assets/database_not_available.html"
- "assets/error.html"
- "assets/footer.html"
- "assets/index.html"
- "assets/main.html"
- "assets/navigation.html"
- "assets/pagination_ellipsis.html"
- "assets/pagination_link_current.html"
- "assets/pagination_link.html"
- "assets/pagination.html"
- "assets/passworded_paste_verify.html"
- "assets/paste.html"
- "assets/pastelist_list.html"
- "assets/pastelist_paste.html"
base: "assets"
prefix: ""

6
go.mod
View File

@@ -3,9 +3,10 @@ module go.dev.pztrn.name/fastpastebin
go 1.16
require (
github.com/alecthomas/chroma v0.10.0
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
github.com/alecthomas/chroma/v2 v2.2.0
github.com/dchest/captcha v1.0.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/dlclark/regexp2 v1.7.0 // indirect
github.com/go-sql-driver/mysql v1.6.0
github.com/jmoiron/sqlx v1.3.5
github.com/kr/pretty v0.3.0 // indirect
@@ -14,7 +15,6 @@ require (
github.com/lib/pq v1.10.6
github.com/pressly/goose v2.7.0+incompatible
github.com/rs/zerolog v1.27.0
go.dev.pztrn.name/flagger v0.0.0-20211119225333-c010875aa337
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
golang.org/x/sys v0.0.0-20220624220833-87e55d714810 // indirect

16
go.sum
View File

@@ -1,16 +1,19 @@
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
github.com/alecthomas/chroma/v2 v2.2.0 h1:Aten8jfQwUqEdadVFFjNyjx7HTexhKP0XuqBG67mRDY=
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae h1:zzGwJfFlFGD94CyyYwCJeSuD32Gj9GTaSi5y9hoVzdY=
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f h1:q/DpyjJjZs94bziQ7YkBmIlpqbVP7yw179rnzoNVX1M=
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f/go.mod h1:QGrK8vMWWHQYQ3QU9bw9Y9OPNfxccGzfb41qjvVeXtY=
github.com/dchest/captcha v1.0.0 h1:vw+bm/qMFvTgcjQlYVTuQBJkarm5R0YSsDKhm1HZI2o=
github.com/dchest/captcha v1.0.0/go.mod h1:7zoElIawLp7GUMLcj54K9kbw+jEyvz2K0FDdRRYhvWo=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -50,15 +53,12 @@ github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs=
github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
go.dev.pztrn.name/flagger v0.0.0-20211119225333-c010875aa337 h1:OerezdlV+T80z1tCzOQg6HSpjheU3dmxHbUbQ8NVSAs=
go.dev.pztrn.name/flagger v0.0.0-20211119225333-c010875aa337/go.mod h1:ttPExQNCubgqqO5Y19LfIBKqmWtBocY7P9MXQEECuZo=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=

View File

@@ -25,7 +25,7 @@
package context
import (
"io/ioutil"
"flag"
"os"
"path/filepath"
@@ -33,7 +33,6 @@ import (
"github.com/rs/zerolog"
"go.dev.pztrn.name/fastpastebin/internal/config"
databaseinterface "go.dev.pztrn.name/fastpastebin/internal/database/interface"
"go.dev.pztrn.name/flagger"
"gopkg.in/yaml.v2"
)
@@ -42,26 +41,18 @@ import (
// contains everything every part of application need, like configuration
// access, logger, etc.
type Context struct {
Config *config.Struct
Database databaseinterface.Interface
Echo *echo.Echo
Flagger *flagger.Flagger
Logger zerolog.Logger
Config *config.Struct
Database databaseinterface.Interface
Echo *echo.Echo
Logger zerolog.Logger
configPathFromCLI string
}
// Initialize initializes context.
func (c *Context) Initialize() {
c.initializeLogger()
c.Flagger = flagger.New("fastpastebin", nil)
c.Flagger.Initialize()
_ = c.Flagger.AddFlag(&flagger.Flag{
Name: "config",
Description: "Configuration file path. Can be overridded with FASTPASTEBIN_CONFIG environment variable (this is what used in tests).",
Type: "string",
DefaultValue: "NO_CONFIG",
})
flag.StringVar(&c.configPathFromCLI, "config", "NO_CONFIG", "Configuration file path. Can be overridded with FASTPASTEBIN_CONFIG environment variable.")
}
// InitializePost initializes everything that needs a configuration.
@@ -76,20 +67,18 @@ func (c *Context) InitializePost() {
func (c *Context) LoadConfiguration() {
c.Logger.Info().Msg("Loading configuration...")
configPath := ""
configPath := c.configPathFromCLI
// We're accepting configuration path from "-config" CLI parameter
// and FASTPASTEBIN_CONFIG environment variable. Later have higher
// weight and can override "-config" value.
configPathFromCLI, err := c.Flagger.GetStringValue("config")
configPathFromEnv, configPathFromEnvFound := os.LookupEnv("FASTPASTEBIN_CONFIG")
if err != nil && configPathFromEnvFound || err == nil && configPathFromEnvFound {
if configPathFromEnvFound {
configPath = configPathFromEnv
} else if err != nil && !configPathFromEnvFound || err == nil && configPathFromCLI == "NO_CONFIG" {
}
if configPath == "NO_CONFIG" {
c.Logger.Panic().Msg("Configuration file path wasn't passed via '-config' or 'FASTPASTEBIN_CONFIG' environment variable. Cannot continue.")
} else if err == nil && !configPathFromEnvFound {
configPath = configPathFromCLI
}
// Normalize file path.
@@ -100,11 +89,11 @@ func (c *Context) LoadConfiguration() {
c.Logger.Debug().Str("path", configPath).Msg("Configuration file path")
// nolint:exhaustruct
//nolint:exhaustruct
c.Config = &config.Struct{}
// Read configuration file.
fileData, err2 := ioutil.ReadFile(normalizedConfigPath)
fileData, err2 := os.ReadFile(normalizedConfigPath)
if err2 != nil {
c.Logger.Panic().Err(err2).Msg("Failed to read configuration file")
}

View File

@@ -26,11 +26,11 @@ package context
const (
// Version .
Version = "0.4.0"
Version = "0.4.1"
)
// New creates new context.
func New() *Context {
// nolint:exhaustruct
//nolint:exhaustruct
return &Context{}
}

View File

@@ -24,7 +24,7 @@ func (c *Context) getMemoryUsage(event *zerolog.Event, level zerolog.Level, mess
// Initializes logger.
func (c *Context) initializeLogger() {
// Устанавливаем форматирование логгера.
// nolint:exhaustruct
//nolint:exhaustruct
output := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: false, TimeFormat: time.RFC3339}
output.FormatLevel = func(lvlRaw interface{}) string {
var lvl string

View File

@@ -79,7 +79,7 @@ func (db *Database) cleanup() {
}
func (db *Database) DeletePaste(pasteID int) error {
// nolint:wrapcheck
//nolint:wrapcheck
return db.db.DeletePaste(pasteID)
}
@@ -92,12 +92,12 @@ func (db *Database) GetDatabaseConnection() *sql.DB {
}
func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) {
// nolint:wrapcheck
//nolint:wrapcheck
return db.db.GetPaste(pasteID)
}
func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) {
// nolint:wrapcheck
//nolint:wrapcheck
return db.db.GetPagedPastes(page)
}
@@ -128,7 +128,7 @@ func (db *Database) RegisterDialect(di dialectinterface.Interface) {
}
func (db *Database) SavePaste(p *structs.Paste) (int64, error) {
// nolint:wrapcheck
//nolint:wrapcheck
return db.db.SavePaste(p)
}

View File

@@ -38,7 +38,7 @@ var (
func New(cc *context.Context) {
ctx = cc
// nolint:exhaustruct
//nolint:exhaustruct
flf = &FlatFiles{}
ctx.Database.RegisterDialect(dialectinterface.Interface(Handler{}))

View File

@@ -27,7 +27,6 @@ package flatfiles
import (
"database/sql"
"encoding/json"
"io/ioutil"
"os"
"os/user"
"path/filepath"
@@ -51,7 +50,7 @@ func (ff *FlatFiles) DeletePaste(pasteID int) error {
if err != nil {
ctx.Logger.Error().Err(err).Msg("Failed to delete paste!")
// nolint:wrapcheck
//nolint:wrapcheck
return err
}
@@ -85,25 +84,25 @@ func (ff *FlatFiles) GetPaste(pasteID int) (*structs.Paste, error) {
pastePath := filepath.Join(ff.path, "pastes", strconv.Itoa(pasteID)+".json")
ctx.Logger.Debug().Str("path", pastePath).Msg("Trying to load paste data")
pasteInBytes, err := ioutil.ReadFile(pastePath)
pasteInBytes, err := os.ReadFile(pastePath)
if err != nil {
ctx.Logger.Debug().Err(err).Msg("Failed to read paste from storage")
// nolint:wrapcheck
//nolint:wrapcheck
return nil, err
}
ctx.Logger.Debug().Int("paste bytes", len(pasteInBytes)).Msg("Loaded paste")
ff.writeMutex.Unlock()
// nolint:exhaustruct
//nolint:exhaustruct
paste := &structs.Paste{}
err1 := json.Unmarshal(pasteInBytes, paste)
if err1 != nil {
ctx.Logger.Error().Err(err1).Msgf("Failed to parse paste")
// nolint:wrapcheck
//nolint:wrapcheck
return nil, err1
}
@@ -149,10 +148,10 @@ func (ff *FlatFiles) GetPagedPastes(page int) ([]structs.Paste, error) {
ctx.Logger.Debug().Int("ID", paste.ID).Int("index", idx).Msg("Getting paste data")
// Get paste data.
// nolint:exhaustruct
//nolint:exhaustruct
pasteData := &structs.Paste{}
pasteRawData, err := ioutil.ReadFile(filepath.Join(ff.path, "pastes", strconv.Itoa(paste.ID)+".json"))
pasteRawData, err := os.ReadFile(filepath.Join(ff.path, "pastes", strconv.Itoa(paste.ID)+".json"))
if err != nil {
ctx.Logger.Error().Err(err).Msg("Failed to read paste data")
@@ -236,7 +235,7 @@ func (ff *FlatFiles) Initialize() {
if _, err := os.Stat(filepath.Join(ff.path, "pastes", "index.json")); err != nil {
ctx.Logger.Warn().Msg("Pastes index file does not exist, will create new one")
} else {
indexData, err := ioutil.ReadFile(filepath.Join(ff.path, "pastes", "index.json"))
indexData, err := os.ReadFile(filepath.Join(ff.path, "pastes", "index.json"))
if err != nil {
ctx.Logger.Fatal().Msg("Failed to read contents of index file!")
}
@@ -253,7 +252,7 @@ func (ff *FlatFiles) Initialize() {
func (ff *FlatFiles) SavePaste(paste *structs.Paste) (int64, error) {
ff.writeMutex.Lock()
// Write paste data on disk.
filesOnDisk, _ := ioutil.ReadDir(filepath.Join(ff.path, "pastes"))
filesOnDisk, _ := os.ReadDir(filepath.Join(ff.path, "pastes"))
pasteID := len(filesOnDisk) + 1
paste.ID = pasteID
@@ -263,20 +262,20 @@ func (ff *FlatFiles) SavePaste(paste *structs.Paste) (int64, error) {
if err != nil {
ff.writeMutex.Unlock()
// nolint:wrapcheck
//nolint:wrapcheck
return 0, err
}
err = ioutil.WriteFile(filepath.Join(ff.path, "pastes", strconv.Itoa(pasteID)+".json"), data, 0o600)
err = os.WriteFile(filepath.Join(ff.path, "pastes", strconv.Itoa(pasteID)+".json"), data, 0o600)
if err != nil {
ff.writeMutex.Unlock()
// nolint:wrapcheck
//nolint:wrapcheck
return 0, err
}
// Add it to cache.
// nolint:exhaustruct
//nolint:exhaustruct
indexData := Index{}
indexData.ID = pasteID
indexData.Private = paste.Private
@@ -296,7 +295,7 @@ func (ff *FlatFiles) Shutdown() {
return
}
err1 := ioutil.WriteFile(filepath.Join(ff.path, "pastes", "index.json"), indexData, 0o600)
err1 := os.WriteFile(filepath.Join(ff.path, "pastes", "index.json"), indexData, 0o600)
if err1 != nil {
ctx.Logger.Error().Err(err1).Msg("Failed to write index data to file. Pretty sure that you've lost your pastes.")

View File

@@ -36,7 +36,7 @@ var (
func New(cc *context.Context) {
ctx = cc
// nolint:exhaustruct
//nolint:exhaustruct
dbAdapter = &Database{}
ctx.Database.RegisterDialect(dialectinterface.Interface(Handler{}))

View File

@@ -38,7 +38,7 @@ func InitialUp(tx *sql.Tx) error {
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 {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}

View File

@@ -31,7 +31,7 @@ import (
func PasteLangUp(tx *sql.Tx) error {
_, err := tx.Exec("ALTER TABLE `pastes` ADD `language` VARCHAR(191) NOT NULL DEFAULT 'text' COMMENT 'Paste language'")
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}
@@ -41,7 +41,7 @@ func PasteLangUp(tx *sql.Tx) error {
func PasteLangDown(tx *sql.Tx) error {
_, err := tx.Exec("ALTER TABLE `pastes` DROP COLUMN `language`")
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}

View File

@@ -31,7 +31,7 @@ import (
func PrivatePastesUp(tx *sql.Tx) error {
_, err := tx.Exec("ALTER TABLE `pastes` ADD `private` BOOL NOT NULL DEFAULT false COMMENT 'Private paste? If true - additional URL parameter (UNIX TIMESTAMP) of paste will be required to access.'")
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}
@@ -41,7 +41,7 @@ func PrivatePastesUp(tx *sql.Tx) error {
func PrivatePastesDown(tx *sql.Tx) error {
_, err := tx.Exec("ALTER TABLE `pastes` DROP COLUMN `private`")
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}

View File

@@ -31,13 +31,13 @@ import (
func PasswordedPastesUp(txn *sql.Tx) error {
_, err := txn.Exec("ALTER TABLE `pastes` ADD `password` varchar(64) NOT NULL DEFAULT '' COMMENT 'Password for paste (scrypted and sha256ed).'")
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}
_, err1 := txn.Exec("ALTER TABLE `pastes` ADD `password_salt` varchar(64) NOT NULL DEFAULT '' COMMENT 'Password salt (sha256ed).'")
if err1 != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err1
}
@@ -47,13 +47,13 @@ func PasswordedPastesUp(txn *sql.Tx) error {
func PasswordedPastesDown(txn *sql.Tx) error {
_, err := txn.Exec("ALTER TABLE `pastes` DROP COLUMN `password`")
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}
_, err1 := txn.Exec("ALTER TABLE `pastes` DROP COLUMN `password_salt`")
if err1 != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err1
}

View File

@@ -59,7 +59,7 @@ func (db *Database) DeletePaste(pasteID int) error {
_, err := db.db.Exec(db.db.Rebind("DELETE FROM pastes WHERE id=?"), pasteID)
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}
@@ -80,12 +80,12 @@ func (db *Database) GetDatabaseConnection() *sql.DB {
func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) {
db.check()
// nolint:exhaustruct
//nolint:exhaustruct
paste := &structs.Paste{}
err := db.db.Get(paste, db.db.Rebind("SELECT * FROM `pastes` WHERE id=?"), pasteID)
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return nil, err
}
@@ -108,7 +108,7 @@ func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) {
err := db.db.Select(&pastesRaw, db.db.Rebind("SELECT * FROM `pastes` WHERE private != true ORDER BY id DESC LIMIT ? OFFSET ?"), ctx.Config.Pastes.Pagination, startPagination)
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return nil, err
}
@@ -191,13 +191,13 @@ func (db *Database) SavePaste(p *structs.Paste) (int64, error) {
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 {
// nolint:wrapcheck
//nolint:wrapcheck
return 0, err
}
lastInsertID, err1 := result.LastInsertId()
if err1 != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return 0, err
}

View File

@@ -36,7 +36,7 @@ var (
func New(cc *context.Context) {
ctx = cc
// nolint:exhaustruct
//nolint:exhaustruct
dbAdapter = &Database{}
ctx.Database.RegisterDialect(dialectinterface.Interface(Handler{}))

View File

@@ -48,7 +48,7 @@ func InitialUp(tx *sql.Tx) error {
COMMENT ON COLUMN pastes.keep_for_unit_type IS 'Keep for unit type. 0 - forever, 1 - minutes, 2 - hours, 3 - days, 4 - months.';
`)
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}

View File

@@ -31,7 +31,7 @@ import (
func PasteLangUp(tx *sql.Tx) error {
_, err := tx.Exec("ALTER TABLE pastes ADD COLUMN language VARCHAR(191) NOT NULL DEFAULT 'text'; COMMENT ON COLUMN pastes.language IS 'Paste language';")
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}
@@ -41,7 +41,7 @@ func PasteLangUp(tx *sql.Tx) error {
func PasteLangDown(tx *sql.Tx) error {
_, err := tx.Exec("ALTER TABLE pastes DROP COLUMN language")
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}

View File

@@ -31,7 +31,7 @@ import (
func PrivatePastesUp(tx *sql.Tx) error {
_, err := tx.Exec("ALTER TABLE pastes ADD COLUMN private BOOLEAN NOT NULL DEFAULT false; COMMENT ON COLUMN pastes.private IS 'Private paste? If true - additional URL parameter (UNIX TIMESTAMP) of paste will be required to access.';")
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}
@@ -41,7 +41,7 @@ func PrivatePastesUp(tx *sql.Tx) error {
func PrivatePastesDown(tx *sql.Tx) error {
_, err := tx.Exec("ALTER TABLE pastes DROP COLUMN private")
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}

View File

@@ -31,13 +31,13 @@ import (
func PasswordedPastesUp(txn *sql.Tx) error {
_, err := txn.Exec("ALTER TABLE pastes ADD COLUMN password VARCHAR(64) NOT NULL DEFAULT ''; COMMENT ON COLUMN pastes.password IS 'Password for paste (scrypted and sha256ed).';")
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}
_, err1 := txn.Exec("ALTER TABLE pastes ADD COLUMN password_salt VARCHAR(64) NOT NULL DEFAULT ''; COMMENT ON COLUMN pastes.password_salt IS 'Password salt (sha256ed).';")
if err1 != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err1
}
@@ -47,13 +47,13 @@ func PasswordedPastesUp(txn *sql.Tx) error {
func PasswordedPastesDown(txn *sql.Tx) error {
_, err := txn.Exec("ALTER TABLE pastes DROP COLUMN password")
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}
_, err1 := txn.Exec("ALTER TABLE pastes DROP COLUMN password_salt")
if err1 != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err1
}

View File

@@ -24,7 +24,7 @@
package postgresql
// nolint:gci
//nolint:gci
import (
"database/sql"
"fmt"
@@ -63,7 +63,7 @@ func (db *Database) DeletePaste(pasteID int) error {
_, err := db.db.Exec(db.db.Rebind("DELETE FROM pastes WHERE id=?"), pasteID)
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}
@@ -84,12 +84,12 @@ func (db *Database) GetDatabaseConnection() *sql.DB {
func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) {
db.check()
// nolint:exhaustruct
//nolint:exhaustruct
paste := &structs.Paste{}
err := db.db.Get(paste, db.db.Rebind("SELECT * FROM pastes WHERE id=$1"), pasteID)
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return nil, err
}
@@ -119,7 +119,7 @@ func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) {
err := db.db.Select(&pastesRaw, db.db.Rebind("SELECT * FROM pastes WHERE private != true ORDER BY id DESC LIMIT $1 OFFSET $2"), ctx.Config.Pastes.Pagination, startPagination)
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return nil, err
}
@@ -203,7 +203,7 @@ func (db *Database) SavePaste(paste *structs.Paste) (int64, error) {
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 {
// nolint:wrapcheck
//nolint:wrapcheck
return 0, err
}
@@ -211,7 +211,7 @@ func (db *Database) SavePaste(paste *structs.Paste) (int64, error) {
err = stmt.Get(&newPasteID, paste)
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return 0, err
}

View File

@@ -37,7 +37,7 @@ var (
// New initializes database structure.
func New(cc *context.Context) {
ctx = cc
// nolint:exhaustruct
//nolint:exhaustruct
dbAdapter = &Database{}
ctx.RegisterDatabaseInterface(databaseinterface.Interface(Handler{}))

View File

@@ -42,13 +42,13 @@ func CreateHTML(currentPage int, pages int, linksBase string) string {
var (
ellipsisStartAdded = false
ellipsisEndAdded = false
// nolint:varnamelen
//nolint:varnamelen
i = 2
)
for i <= pages {
// ToDo: fix it!
// nolint:nestif
//nolint:nestif
if pages > 5 {
if currentPage-3 < i && currentPage+3 > i || i == pages {
paginationItemRaw := string(paginationLinkRaw)

View File

@@ -76,7 +76,7 @@ type Paste struct {
func (p *Paste) CreatePassword(password string) error {
// Create salt - random string.
// Yes, it is insecure. Should be refactored!
// nolint:gosec
//nolint:gosec
seededRand := rand.New(rand.NewSource(time.Now().UnixNano()))
saltBytes := make([]byte, 64)
@@ -90,7 +90,7 @@ func (p *Paste) CreatePassword(password string) error {
// Create crypted password and hash it.
passwordCrypted, err := scrypt.Key([]byte(password), []byte(p.PasswordSalt), 131072, 8, 1, 64)
if err != nil {
// nolint:wrapcheck
//nolint:wrapcheck
return err
}