Compare commits
15 Commits
f8f0302564
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
b87921c811
|
|||
|
74ea9b6863
|
|||
|
30f8b4975c
|
|||
|
dcd361de1f
|
|||
|
2ec0e28243
|
|||
|
df5671586e
|
|||
|
59dafc373f
|
|||
|
25489dc103
|
|||
|
1dc6dfe00e
|
|||
|
02e933efed
|
|||
|
d2b3304a5a
|
|||
|
9164c53c54
|
|||
|
18734ebd18
|
|||
|
6b04a1dcd5
|
|||
|
1cb93c7d97
|
18
.drone.yml
18
.drone.yml
@@ -5,14 +5,16 @@ name: lint and test
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: lint
|
- 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:
|
environment:
|
||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
commands:
|
commands:
|
||||||
- golangci-lint run
|
- golangci-lint run
|
||||||
|
|
||||||
- name: test
|
- name: test
|
||||||
image: golang:1.18.3-alpine
|
image: code.pztrn.name/containers/mirror/golang:1.19.0-alpine
|
||||||
|
pull: if-not-exists
|
||||||
environment:
|
environment:
|
||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
commands:
|
commands:
|
||||||
@@ -28,7 +30,9 @@ depends_on:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: build master image
|
- 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:
|
when:
|
||||||
branch: ["master"]
|
branch: ["master"]
|
||||||
settings:
|
settings:
|
||||||
@@ -36,11 +40,13 @@ steps:
|
|||||||
username: drone
|
username: drone
|
||||||
password:
|
password:
|
||||||
from_secret: drone_secret
|
from_secret: drone_secret
|
||||||
repo: code.pztrn.name/pztrn/fastpastebin
|
repo: code.pztrn.name/apps/fastpastebin
|
||||||
auto_tag: true
|
auto_tag: true
|
||||||
|
|
||||||
- name: build tagged image
|
- 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:
|
when:
|
||||||
event: ["tag"]
|
event: ["tag"]
|
||||||
settings:
|
settings:
|
||||||
@@ -48,5 +54,5 @@ steps:
|
|||||||
username: drone
|
username: drone
|
||||||
password:
|
password:
|
||||||
from_secret: drone_secret
|
from_secret: drone_secret
|
||||||
repo: code.pztrn.name/pztrn/fastpastebin
|
repo: code.pztrn.name/apps/fastpastebin
|
||||||
auto_tag: true
|
auto_tag: true
|
||||||
|
|||||||
5
.markdownlint.json
Normal file
5
.markdownlint.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"line-length": false,
|
||||||
|
"first-line-h1": false,
|
||||||
|
"no-duplicate-header": false
|
||||||
|
}
|
||||||
82
CHANGELOG.md
82
CHANGELOG.md
@@ -1,12 +1,84 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
``[A]`` - added
|
All notable changes to this project will be documented in this file.
|
||||||
``[F]`` - fixed
|
|
||||||
``[R]`` - removed
|
|
||||||
|
|
||||||
---
|
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
|
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
|
||||||
|
|||||||
@@ -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
|
WORKDIR /fastpastebin
|
||||||
COPY . .
|
COPY . .
|
||||||
@@ -7,7 +7,7 @@ WORKDIR /fastpastebin/cmd/fastpastebin
|
|||||||
|
|
||||||
RUN CGO_ENABLED=0 go build -tags netgo
|
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>"
|
LABEL maintainer "Stanislav N. <pztrn@pztrn.name>"
|
||||||
|
|
||||||
COPY --from=build /fastpastebin/cmd/fastpastebin/fastpastebin /app/fastpastebin
|
COPY --from=build /fastpastebin/cmd/fastpastebin/fastpastebin /app/fastpastebin
|
||||||
|
|||||||
52
README.md
52
README.md
@@ -1,9 +1,13 @@
|
|||||||
# Fast Pastebin
|
# Fast Pastebin
|
||||||
|
|
||||||
[](https://github-ci.pztrn.name/pztrn/fastpastebin) 
|
[](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!
|
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!**
|
||||||
|
|
||||||
|
Also, [join Matrix room](https://matrix.to/#/%23fastpastebin:pztrn.online?via=matrix.org) for near-realtime chat.
|
||||||
|
|
||||||
## Current functionality
|
## Current functionality
|
||||||
|
|
||||||
* Create and view public and private pastes.
|
* Create and view public and private pastes.
|
||||||
@@ -14,18 +18,41 @@ Easy-to-use-and-install pastebin software written in Go. No bells or whistles, n
|
|||||||
|
|
||||||
## Caveats
|
## 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
|
## Installation and updating
|
||||||
|
|
||||||
Just issue:
|
Just issue:
|
||||||
|
|
||||||
```bash
|
```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@VERSION
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Replace `VERSION` with a [tag of your choice](https://code.pztrn.name/apps/fastpastebin/releases).
|
||||||
|
|
||||||
This command can be used to update Fast Paste Bin.
|
This command can be used to update Fast Paste Bin.
|
||||||
|
|
||||||
|
Also Fast Paste Bin is dockerized, see [here](https://code.pztrn.name/apps/-/packages/container/fastpastebin) for instructions.
|
||||||
|
|
||||||
|
Compose file with resources limits, as used by me:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
version: "2.4"
|
||||||
|
|
||||||
|
services:
|
||||||
|
fastpastebin:
|
||||||
|
restart: always
|
||||||
|
image: code.pztrn.name/apps/fastpastebin:0.4.1
|
||||||
|
volumes:
|
||||||
|
- "./fastpastebin.yaml:/app/fastpastebin.yaml"
|
||||||
|
ports:
|
||||||
|
- "25544:25544"
|
||||||
|
cpus: 2
|
||||||
|
mem_limit: 1G
|
||||||
|
memswap_limit: 0
|
||||||
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Take a look at [example configuration file](examples/fastpastebin.yaml.dist) which contains all supported options and their descriptions.
|
Take a look at [example configuration file](examples/fastpastebin.yaml.dist) which contains all supported options and their descriptions.
|
||||||
@@ -34,18 +61,21 @@ Configuration file position is irrelevant, there is no hardcoded paths where Fas
|
|||||||
|
|
||||||
## Developing
|
## 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:
|
### Branching, versions, etc
|
||||||
|
|
||||||
```bash
|
There is a `develop` branch which represents current development state. **All new commits (by me) and merge requests (by others) should go to that branch**.
|
||||||
fileb0x fileb0x.yml
|
|
||||||
```
|
|
||||||
|
|
||||||
Also if you're changed list of assets (by creating or deleting them) be sure to fix files list in ``fileb0x.yml`` file!
|
Branch `master` represents "latest version" state and always stable.
|
||||||
|
|
||||||
The rest is default - use linters, formatters, etc. VSCode with Go plugin is recommended for developing as it will perform most of linting-formatting
|
### Code
|
||||||
actions automagically. Try to follow [Go's code review comments](https://github.com/golang/go/wiki/CodeReviewComments) with few exceptions:
|
|
||||||
|
Use linters, formatters, etc. VSCode with Go plugin is recommended for developing as it will perform most of linting-formatting
|
||||||
|
actions automagically.
|
||||||
|
|
||||||
|
Also, Sublime Text with LSP-gopls will also work just fine.
|
||||||
|
|
||||||
|
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.
|
* We're not forcing any limits on line length for code, only for comments, they should be 72-76 chars long.
|
||||||
|
|
||||||
## ToDo
|
## ToDo
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//nolint:gofmt,gofumpt,goimports
|
||||||
package assets
|
package assets
|
||||||
|
|
||||||
import "embed"
|
import "embed"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<strong>{version}</strong> by
|
<strong>{version}</strong> by
|
||||||
<a href="https://pztrn.name">Stanislav N. aka pztrn</a>. The source code is licensed
|
<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="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>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -38,13 +38,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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">
|
<label class="checkbox">
|
||||||
<input type="checkbox" name="paste-private" id="paste-private"> Private paste with unique URL?
|
<input type="checkbox" name="paste-private" id="paste-private"> Private paste with unique URL?
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>OR</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>
|
<label for="paste-password">Password for paste:</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input class="input" type="text" placeholder="Enter password." name="paste-password" id="paste-password">
|
<input class="input" type="text" placeholder="Enter password." name="paste-password" id="paste-password">
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Fast Paste Bin</title>
|
<title>Fast Paste Bin</title>
|
||||||
<link rel="stylesheet" href="/static/css/bulma-0.7.5.min.css">
|
<link rel="stylesheet" href="/static/css/bulma-0.9.4.min.css">
|
||||||
<link rel="stylesheet" href="/static/css/bulma-tooltip-3.0.0.min.css">
|
<link rel="stylesheet" href="/static/css/bulma-tooltip-1.2.min.css">
|
||||||
<link rel="stylesheet" href="/static/css/style.css">
|
<link rel="stylesheet" href="/static/css/style.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|||||||
1
assets/static/css/bulma-0.7.5.min.css
vendored
1
assets/static/css/bulma-0.7.5.min.css
vendored
File diff suppressed because one or more lines are too long
1
assets/static/css/bulma-0.9.4.min.css
vendored
Normal file
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
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
@@ -25,6 +25,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
@@ -48,7 +49,7 @@ func main() {
|
|||||||
// to be added.
|
// to be added.
|
||||||
|
|
||||||
// Parse flags.
|
// Parse flags.
|
||||||
appCtx.Flagger.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// Continue loading.
|
// Continue loading.
|
||||||
appCtx.LoadConfiguration()
|
appCtx.LoadConfiguration()
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ import (
|
|||||||
func dbNotAvailableGet(ec echo.Context) error {
|
func dbNotAvailableGet(ec echo.Context) error {
|
||||||
htmlData := templater.GetTemplate(ec, "database_not_available.html", nil)
|
htmlData := templater.GetTemplate(ec, "database_not_available.html", nil)
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ec.HTML(http.StatusInternalServerError, htmlData)
|
return ec.HTML(http.StatusInternalServerError, htmlData)
|
||||||
}
|
}
|
||||||
|
|
||||||
func dbNotAvailableRawGet(ec echo.Context) error {
|
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.")
|
return ec.String(http.StatusInternalServerError, "Database not available\nSomething went wrong while trying to connect to database. Check logs for details.")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ package indexpage
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/alecthomas/chroma/lexers"
|
"github.com/alecthomas/chroma/v2/lexers"
|
||||||
"github.com/labstack/echo"
|
"github.com/labstack/echo"
|
||||||
"go.dev.pztrn.name/fastpastebin/internal/captcha"
|
"go.dev.pztrn.name/fastpastebin/internal/captcha"
|
||||||
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/flatfiles"
|
"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.
|
// We should check if database connection available.
|
||||||
dbConn := ctx.Database.GetDatabaseConnection()
|
dbConn := ctx.Database.GetDatabaseConnection()
|
||||||
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
|
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.Redirect(http.StatusFound, "/database_not_available")
|
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})
|
htmlData := templater.GetTemplate(ectx, "index.html", map[string]string{"lexers": availableLexersSelectOpts, "captchaString": captchaString})
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusOK, htmlData)
|
return ectx.HTML(http.StatusOK, htmlData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alecthomas/chroma"
|
htmlfmt "github.com/alecthomas/chroma/v2/formatters/html"
|
||||||
htmlfmt "github.com/alecthomas/chroma/formatters/html"
|
"github.com/alecthomas/chroma/v2/lexers"
|
||||||
"github.com/alecthomas/chroma/lexers"
|
"github.com/alecthomas/chroma/v2/styles"
|
||||||
"github.com/alecthomas/chroma/styles"
|
|
||||||
"github.com/labstack/echo"
|
"github.com/labstack/echo"
|
||||||
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/flatfiles"
|
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/flatfiles"
|
||||||
"go.dev.pztrn.name/fastpastebin/internal/structs"
|
"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")
|
errtpl := templater.GetErrorTemplate(ectx, "Paste #"+pasteIDStr+" not found")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusBadRequest, errtpl)
|
return ectx.HTML(http.StatusBadRequest, errtpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +114,7 @@ func pasteGETWebInterface(ectx echo.Context) error {
|
|||||||
if err == pasteExpired || err == pasteNotFound || err == pasteTimestampInvalid {
|
if err == pasteExpired || err == pasteNotFound || err == pasteTimestampInvalid {
|
||||||
errtpl := templater.GetErrorTemplate(ectx, "Paste #"+pasteIDRaw+" not found")
|
errtpl := templater.GetErrorTemplate(ectx, "Paste #"+pasteIDRaw+" not found")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusNotFound, errtpl)
|
return ectx.HTML(http.StatusNotFound, errtpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +123,7 @@ func pasteGETWebInterface(ectx echo.Context) error {
|
|||||||
if err == pasteCookieInvalid {
|
if err == pasteCookieInvalid {
|
||||||
ctx.Logger.Info().Int("paste ID", pasteID).Msg("Invalid cookie, redirecting to auth page")
|
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")
|
return ectx.Redirect(http.StatusMovedPermanently, "/paste/"+pasteIDStr+"/"+ectx.Param("timestamp")+"/verify")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +166,7 @@ func pasteGETWebInterface(ectx echo.Context) error {
|
|||||||
style = styles.Fallback
|
style = styles.Fallback
|
||||||
}
|
}
|
||||||
// Get HTML formatter.
|
// 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.
|
// Create buffer and format into it.
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
@@ -182,7 +181,7 @@ func pasteGETWebInterface(ectx echo.Context) error {
|
|||||||
// Get template and format it.
|
// Get template and format it.
|
||||||
pasteHTML := templater.GetTemplate(ectx, "paste.html", pasteData)
|
pasteHTML := templater.GetTemplate(ectx, "paste.html", pasteData)
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusOK, pasteHTML)
|
return ectx.HTML(http.StatusOK, pasteHTML)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +200,7 @@ func pastePasswordedVerifyGet(ectx echo.Context) error {
|
|||||||
|
|
||||||
errtpl := templater.GetErrorTemplate(ectx, "Paste #"+pasteIDRaw+" not found")
|
errtpl := templater.GetErrorTemplate(ectx, "Paste #"+pasteIDRaw+" not found")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusBadRequest, errtpl)
|
return ectx.HTML(http.StatusBadRequest, errtpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +216,7 @@ func pastePasswordedVerifyGet(ectx echo.Context) error {
|
|||||||
if cookieValue == cookie.Value {
|
if cookieValue == cookie.Value {
|
||||||
ctx.Logger.Info().Msg("Valid cookie, redirecting to paste page...")
|
ctx.Logger.Info().Msg("Valid cookie, redirecting to paste page...")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.Redirect(http.StatusMovedPermanently, "/paste/"+pasteIDRaw+"/"+ectx.Param("timestamp"))
|
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)
|
verifyHTML := templater.GetTemplate(ectx, "passworded_paste_verify.html", htmlData)
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusOK, verifyHTML)
|
return ectx.HTML(http.StatusOK, verifyHTML)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +240,7 @@ func pastePasswordedVerifyPost(ectx echo.Context) error {
|
|||||||
dbConn := ctx.Database.GetDatabaseConnection()
|
dbConn := ctx.Database.GetDatabaseConnection()
|
||||||
|
|
||||||
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
|
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.Redirect(http.StatusFound, "/database_not_available")
|
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")
|
ctx.Logger.Error().Err(err1).Int("paste ID", pasteID).Msg("Failed to get paste")
|
||||||
errtpl := templater.GetErrorTemplate(ectx, "Paste #"+strconv.Itoa(pasteID)+" not found")
|
errtpl := templater.GetErrorTemplate(ectx, "Paste #"+strconv.Itoa(pasteID)+" not found")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusBadRequest, errtpl)
|
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")
|
errtpl := templater.GetErrorTemplate(ectx, "Paste #"+strconv.Itoa(pasteID)+" not found")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusBadRequest, errtpl)
|
return ectx.HTML(http.StatusBadRequest, errtpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,13 +280,13 @@ func pastePasswordedVerifyPost(ectx echo.Context) error {
|
|||||||
cookie.Expires = time.Now().Add(24 * time.Hour)
|
cookie.Expires = time.Now().Add(24 * time.Hour)
|
||||||
ectx.SetCookie(cookie)
|
ectx.SetCookie(cookie)
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.Redirect(http.StatusFound, "/paste/"+strconv.Itoa(pasteID)+"/"+timestampRaw)
|
return ectx.Redirect(http.StatusFound, "/paste/"+strconv.Itoa(pasteID)+"/"+timestampRaw)
|
||||||
}
|
}
|
||||||
|
|
||||||
errtpl := templater.GetErrorTemplate(ectx, "Invalid password. Please, try again.")
|
errtpl := templater.GetErrorTemplate(ectx, "Invalid password. Please, try again.")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusBadRequest, errtpl)
|
return ectx.HTML(http.StatusBadRequest, errtpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +296,7 @@ func pasteRawGETWebInterface(ectx echo.Context) error {
|
|||||||
// We should check if database connection available.
|
// We should check if database connection available.
|
||||||
dbConn := ctx.Database.GetDatabaseConnection()
|
dbConn := ctx.Database.GetDatabaseConnection()
|
||||||
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
|
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.Redirect(http.StatusFound, "/database_not_available/raw")
|
return ectx.Redirect(http.StatusFound, "/database_not_available/raw")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,14 +311,14 @@ func pasteRawGETWebInterface(ectx echo.Context) error {
|
|||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
ctx.Logger.Error().Err(err1).Int("paste ID", pasteID).Msg("Failed to get paste from database")
|
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.")
|
return ectx.HTML(http.StatusBadRequest, "Paste #"+pasteIDRaw+" does not exist.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if paste.IsExpired() {
|
if paste.IsExpired() {
|
||||||
ctx.Logger.Error().Int("paste ID", pasteID).Msg("Paste is expired")
|
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.")
|
return ectx.HTML(http.StatusBadRequest, "Paste #"+pasteIDRaw+" does not exist.")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,7 +330,7 @@ func pasteRawGETWebInterface(ectx echo.Context) error {
|
|||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
ctx.Logger.Error().Err(err2).Int("paste ID", pasteID).Str("provided timestamp", tsProvidedStr).Msg("Invalid timestamp provided for getting private paste")
|
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")
|
return ectx.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,12 +338,12 @@ func pasteRawGETWebInterface(ectx echo.Context) error {
|
|||||||
if tsProvided != pasteTS {
|
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")
|
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")
|
return ectx.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint
|
//nolint
|
||||||
// ToDo: figure out how to handle passworded pastes here.
|
// ToDo: figure out how to handle passworded pastes here.
|
||||||
// Return error for now.
|
// Return error for now.
|
||||||
if paste.Password != "" {
|
if paste.Password != "" {
|
||||||
@@ -352,6 +351,6 @@ func pasteRawGETWebInterface(ectx echo.Context) error {
|
|||||||
return ectx.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found")
|
return ectx.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.String(http.StatusOK, paste.Data)
|
return ectx.String(http.StatusOK, paste.Data)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alecthomas/chroma/lexers"
|
"github.com/alecthomas/chroma/v2/lexers"
|
||||||
"github.com/labstack/echo"
|
"github.com/labstack/echo"
|
||||||
"go.dev.pztrn.name/fastpastebin/internal/captcha"
|
"go.dev.pztrn.name/fastpastebin/internal/captcha"
|
||||||
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/flatfiles"
|
"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.
|
// We should check if database connection available.
|
||||||
dbConn := ctx.Database.GetDatabaseConnection()
|
dbConn := ctx.Database.GetDatabaseConnection()
|
||||||
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
|
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.Redirect(http.StatusFound, "/database_not_available")
|
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")
|
errtpl := templater.GetErrorTemplate(ectx, "Cannot create empty paste")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusBadRequest, errtpl)
|
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.")
|
errtpl := templater.GetErrorTemplate(ectx, "Empty pastes aren't allowed.")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusBadRequest, errtpl)
|
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 ;).")
|
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)
|
return ectx.HTML(http.StatusBadRequest, errtpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,11 +65,11 @@ func pastePOSTWebInterface(ectx echo.Context) error {
|
|||||||
|
|
||||||
errtpl := templater.GetErrorTemplate(ectx, "Invalid captcha solution.")
|
errtpl := templater.GetErrorTemplate(ectx, "Invalid captcha solution.")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusBadRequest, errtpl)
|
return ectx.HTML(http.StatusBadRequest, errtpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:exhaustruct
|
//nolint:exhaustruct
|
||||||
paste := &structs.Paste{
|
paste := &structs.Paste{
|
||||||
Title: params["paste-title"][0],
|
Title: params["paste-title"][0],
|
||||||
Data: params["paste-contents"][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 ;).")
|
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)
|
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.")
|
errtpl := templater.GetErrorTemplate(ectx, "Failed to save paste. Please, try again later.")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusBadRequest, errtpl)
|
return ectx.HTML(http.StatusBadRequest, errtpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,10 +153,10 @@ func pastePOSTWebInterface(ectx echo.Context) error {
|
|||||||
|
|
||||||
// Private pastes have it's timestamp in URL.
|
// Private pastes have it's timestamp in URL.
|
||||||
if paste.Private {
|
if paste.Private {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.Redirect(http.StatusFound, "/paste/"+newPasteIDAsString+"/"+strconv.FormatInt(paste.CreatedAt.Unix(), 10))
|
return ectx.Redirect(http.StatusFound, "/paste/"+newPasteIDAsString+"/"+strconv.FormatInt(paste.CreatedAt.Unix(), 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.Redirect(http.StatusFound, "/paste/"+newPasteIDAsString)
|
return ectx.Redirect(http.StatusFound, "/paste/"+newPasteIDAsString)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func pastesGET(ectx echo.Context) error {
|
|||||||
// We should check if database connection available.
|
// We should check if database connection available.
|
||||||
dbConn := ctx.Database.GetDatabaseConnection()
|
dbConn := ctx.Database.GetDatabaseConnection()
|
||||||
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
|
if ctx.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.Redirect(http.StatusFound, "/database_not_available")
|
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.")
|
noPastesToShowTpl := templater.GetErrorTemplate(ectx, "No pastes to show.")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusOK, noPastesToShowTpl)
|
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})
|
pasteListTpl := templater.GetTemplate(ectx, "pastelist_list.html", map[string]string{"pastes": pastesString, "pagination": paginationHTML})
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return ectx.HTML(http.StatusOK, pasteListTpl)
|
return ectx.HTML(http.StatusOK, pasteListTpl)
|
||||||
}
|
}
|
||||||
|
|||||||
112
fileb0x.yml
112
fileb0x.yml
@@ -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
6
go.mod
@@ -3,9 +3,10 @@ module go.dev.pztrn.name/fastpastebin
|
|||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alecthomas/chroma v0.10.0
|
github.com/alecthomas/chroma/v2 v2.2.0
|
||||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
|
github.com/dchest/captcha v1.0.0
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
|
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/go-sql-driver/mysql v1.6.0
|
||||||
github.com/jmoiron/sqlx v1.3.5
|
github.com/jmoiron/sqlx v1.3.5
|
||||||
github.com/kr/pretty v0.3.0 // indirect
|
github.com/kr/pretty v0.3.0 // indirect
|
||||||
@@ -14,7 +15,6 @@ require (
|
|||||||
github.com/lib/pq v1.10.6
|
github.com/lib/pq v1.10.6
|
||||||
github.com/pressly/goose v2.7.0+incompatible
|
github.com/pressly/goose v2.7.0+incompatible
|
||||||
github.com/rs/zerolog v1.27.0
|
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/crypto v0.0.0-20220622213112-05595931fe9d
|
||||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
|
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
|
||||||
golang.org/x/sys v0.0.0-20220624220833-87e55d714810 // indirect
|
golang.org/x/sys v0.0.0-20220624220833-87e55d714810 // indirect
|
||||||
|
|||||||
16
go.sum
16
go.sum
@@ -1,16 +1,19 @@
|
|||||||
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
|
github.com/alecthomas/chroma/v2 v2.2.0 h1:Aten8jfQwUqEdadVFFjNyjx7HTexhKP0XuqBG67mRDY=
|
||||||
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
|
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/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/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.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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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 v1.0.0 h1:vw+bm/qMFvTgcjQlYVTuQBJkarm5R0YSsDKhm1HZI2o=
|
||||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f/go.mod h1:QGrK8vMWWHQYQ3QU9bw9Y9OPNfxccGzfb41qjvVeXtY=
|
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 h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
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.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 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
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=
|
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 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs=
|
||||||
github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U=
|
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/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 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
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 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
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 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
|
||||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
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 h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
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=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
package context
|
package context
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"flag"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
@@ -33,7 +33,6 @@ import (
|
|||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"go.dev.pztrn.name/fastpastebin/internal/config"
|
"go.dev.pztrn.name/fastpastebin/internal/config"
|
||||||
databaseinterface "go.dev.pztrn.name/fastpastebin/internal/database/interface"
|
databaseinterface "go.dev.pztrn.name/fastpastebin/internal/database/interface"
|
||||||
"go.dev.pztrn.name/flagger"
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -42,26 +41,18 @@ import (
|
|||||||
// contains everything every part of application need, like configuration
|
// contains everything every part of application need, like configuration
|
||||||
// access, logger, etc.
|
// access, logger, etc.
|
||||||
type Context struct {
|
type Context struct {
|
||||||
Config *config.Struct
|
Config *config.Struct
|
||||||
Database databaseinterface.Interface
|
Database databaseinterface.Interface
|
||||||
Echo *echo.Echo
|
Echo *echo.Echo
|
||||||
Flagger *flagger.Flagger
|
Logger zerolog.Logger
|
||||||
Logger zerolog.Logger
|
configPathFromCLI string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize initializes context.
|
// Initialize initializes context.
|
||||||
func (c *Context) Initialize() {
|
func (c *Context) Initialize() {
|
||||||
c.initializeLogger()
|
c.initializeLogger()
|
||||||
|
|
||||||
c.Flagger = flagger.New("fastpastebin", nil)
|
flag.StringVar(&c.configPathFromCLI, "config", "NO_CONFIG", "Configuration file path. Can be overridded with FASTPASTEBIN_CONFIG environment variable.")
|
||||||
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",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitializePost initializes everything that needs a configuration.
|
// InitializePost initializes everything that needs a configuration.
|
||||||
@@ -76,20 +67,18 @@ func (c *Context) InitializePost() {
|
|||||||
func (c *Context) LoadConfiguration() {
|
func (c *Context) LoadConfiguration() {
|
||||||
c.Logger.Info().Msg("Loading configuration...")
|
c.Logger.Info().Msg("Loading configuration...")
|
||||||
|
|
||||||
configPath := ""
|
configPath := c.configPathFromCLI
|
||||||
|
|
||||||
// We're accepting configuration path from "-config" CLI parameter
|
// We're accepting configuration path from "-config" CLI parameter
|
||||||
// and FASTPASTEBIN_CONFIG environment variable. Later have higher
|
// and FASTPASTEBIN_CONFIG environment variable. Later have higher
|
||||||
// weight and can override "-config" value.
|
// weight and can override "-config" value.
|
||||||
configPathFromCLI, err := c.Flagger.GetStringValue("config")
|
|
||||||
configPathFromEnv, configPathFromEnvFound := os.LookupEnv("FASTPASTEBIN_CONFIG")
|
configPathFromEnv, configPathFromEnvFound := os.LookupEnv("FASTPASTEBIN_CONFIG")
|
||||||
|
if configPathFromEnvFound {
|
||||||
if err != nil && configPathFromEnvFound || err == nil && configPathFromEnvFound {
|
|
||||||
configPath = configPathFromEnv
|
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.")
|
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.
|
// Normalize file path.
|
||||||
@@ -100,11 +89,11 @@ func (c *Context) LoadConfiguration() {
|
|||||||
|
|
||||||
c.Logger.Debug().Str("path", configPath).Msg("Configuration file path")
|
c.Logger.Debug().Str("path", configPath).Msg("Configuration file path")
|
||||||
|
|
||||||
// nolint:exhaustruct
|
//nolint:exhaustruct
|
||||||
c.Config = &config.Struct{}
|
c.Config = &config.Struct{}
|
||||||
|
|
||||||
// Read configuration file.
|
// Read configuration file.
|
||||||
fileData, err2 := ioutil.ReadFile(normalizedConfigPath)
|
fileData, err2 := os.ReadFile(normalizedConfigPath)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
c.Logger.Panic().Err(err2).Msg("Failed to read configuration file")
|
c.Logger.Panic().Err(err2).Msg("Failed to read configuration file")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,11 +26,11 @@ package context
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// Version .
|
// Version .
|
||||||
Version = "0.4.0"
|
Version = "0.4.1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// New creates new context.
|
// New creates new context.
|
||||||
func New() *Context {
|
func New() *Context {
|
||||||
// nolint:exhaustruct
|
//nolint:exhaustruct
|
||||||
return &Context{}
|
return &Context{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func (c *Context) getMemoryUsage(event *zerolog.Event, level zerolog.Level, mess
|
|||||||
// Initializes logger.
|
// Initializes logger.
|
||||||
func (c *Context) initializeLogger() {
|
func (c *Context) initializeLogger() {
|
||||||
// Устанавливаем форматирование логгера.
|
// Устанавливаем форматирование логгера.
|
||||||
// nolint:exhaustruct
|
//nolint:exhaustruct
|
||||||
output := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: false, TimeFormat: time.RFC3339}
|
output := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: false, TimeFormat: time.RFC3339}
|
||||||
output.FormatLevel = func(lvlRaw interface{}) string {
|
output.FormatLevel = func(lvlRaw interface{}) string {
|
||||||
var lvl string
|
var lvl string
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ func (db *Database) cleanup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (db *Database) DeletePaste(pasteID int) error {
|
func (db *Database) DeletePaste(pasteID int) error {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return db.db.DeletePaste(pasteID)
|
return db.db.DeletePaste(pasteID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,12 +92,12 @@ func (db *Database) GetDatabaseConnection() *sql.DB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) {
|
func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return db.db.GetPaste(pasteID)
|
return db.db.GetPaste(pasteID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) {
|
func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return db.db.GetPagedPastes(page)
|
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) {
|
func (db *Database) SavePaste(p *structs.Paste) (int64, error) {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return db.db.SavePaste(p)
|
return db.db.SavePaste(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ var (
|
|||||||
|
|
||||||
func New(cc *context.Context) {
|
func New(cc *context.Context) {
|
||||||
ctx = cc
|
ctx = cc
|
||||||
// nolint:exhaustruct
|
//nolint:exhaustruct
|
||||||
flf = &FlatFiles{}
|
flf = &FlatFiles{}
|
||||||
|
|
||||||
ctx.Database.RegisterDialect(dialectinterface.Interface(Handler{}))
|
ctx.Database.RegisterDialect(dialectinterface.Interface(Handler{}))
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ package flatfiles
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -51,7 +50,7 @@ func (ff *FlatFiles) DeletePaste(pasteID int) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Logger.Error().Err(err).Msg("Failed to delete paste!")
|
ctx.Logger.Error().Err(err).Msg("Failed to delete paste!")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
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")
|
pastePath := filepath.Join(ff.path, "pastes", strconv.Itoa(pasteID)+".json")
|
||||||
ctx.Logger.Debug().Str("path", pastePath).Msg("Trying to load paste data")
|
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 {
|
if err != nil {
|
||||||
ctx.Logger.Debug().Err(err).Msg("Failed to read paste from storage")
|
ctx.Logger.Debug().Err(err).Msg("Failed to read paste from storage")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Logger.Debug().Int("paste bytes", len(pasteInBytes)).Msg("Loaded paste")
|
ctx.Logger.Debug().Int("paste bytes", len(pasteInBytes)).Msg("Loaded paste")
|
||||||
ff.writeMutex.Unlock()
|
ff.writeMutex.Unlock()
|
||||||
|
|
||||||
// nolint:exhaustruct
|
//nolint:exhaustruct
|
||||||
paste := &structs.Paste{}
|
paste := &structs.Paste{}
|
||||||
|
|
||||||
err1 := json.Unmarshal(pasteInBytes, paste)
|
err1 := json.Unmarshal(pasteInBytes, paste)
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
ctx.Logger.Error().Err(err1).Msgf("Failed to parse paste")
|
ctx.Logger.Error().Err(err1).Msgf("Failed to parse paste")
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return nil, err1
|
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")
|
ctx.Logger.Debug().Int("ID", paste.ID).Int("index", idx).Msg("Getting paste data")
|
||||||
|
|
||||||
// Get paste data.
|
// Get paste data.
|
||||||
// nolint:exhaustruct
|
//nolint:exhaustruct
|
||||||
pasteData := &structs.Paste{}
|
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 {
|
if err != nil {
|
||||||
ctx.Logger.Error().Err(err).Msg("Failed to read paste data")
|
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 {
|
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")
|
ctx.Logger.Warn().Msg("Pastes index file does not exist, will create new one")
|
||||||
} else {
|
} 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 {
|
if err != nil {
|
||||||
ctx.Logger.Fatal().Msg("Failed to read contents of index file!")
|
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) {
|
func (ff *FlatFiles) SavePaste(paste *structs.Paste) (int64, error) {
|
||||||
ff.writeMutex.Lock()
|
ff.writeMutex.Lock()
|
||||||
// Write paste data on disk.
|
// 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
|
pasteID := len(filesOnDisk) + 1
|
||||||
paste.ID = pasteID
|
paste.ID = pasteID
|
||||||
|
|
||||||
@@ -263,20 +262,20 @@ func (ff *FlatFiles) SavePaste(paste *structs.Paste) (int64, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
ff.writeMutex.Unlock()
|
ff.writeMutex.Unlock()
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return 0, err
|
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 {
|
if err != nil {
|
||||||
ff.writeMutex.Unlock()
|
ff.writeMutex.Unlock()
|
||||||
|
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add it to cache.
|
// Add it to cache.
|
||||||
// nolint:exhaustruct
|
//nolint:exhaustruct
|
||||||
indexData := Index{}
|
indexData := Index{}
|
||||||
indexData.ID = pasteID
|
indexData.ID = pasteID
|
||||||
indexData.Private = paste.Private
|
indexData.Private = paste.Private
|
||||||
@@ -296,7 +295,7 @@ func (ff *FlatFiles) Shutdown() {
|
|||||||
return
|
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 {
|
if err1 != nil {
|
||||||
ctx.Logger.Error().Err(err1).Msg("Failed to write index data to file. Pretty sure that you've lost your pastes.")
|
ctx.Logger.Error().Err(err1).Msg("Failed to write index data to file. Pretty sure that you've lost your pastes.")
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ var (
|
|||||||
|
|
||||||
func New(cc *context.Context) {
|
func New(cc *context.Context) {
|
||||||
ctx = cc
|
ctx = cc
|
||||||
// nolint:exhaustruct
|
//nolint:exhaustruct
|
||||||
dbAdapter = &Database{}
|
dbAdapter = &Database{}
|
||||||
|
|
||||||
ctx.Database.RegisterDialect(dialectinterface.Interface(Handler{}))
|
ctx.Database.RegisterDialect(dialectinterface.Interface(Handler{}))
|
||||||
|
|||||||
@@ -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.',
|
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';`)
|
PRIMARY KEY (id), UNIQUE KEY id (id)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='Pastes';`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import (
|
|||||||
func PasteLangUp(tx *sql.Tx) error {
|
func PasteLangUp(tx *sql.Tx) error {
|
||||||
_, err := tx.Exec("ALTER TABLE `pastes` ADD `language` VARCHAR(191) NOT NULL DEFAULT 'text' COMMENT 'Paste language'")
|
_, err := tx.Exec("ALTER TABLE `pastes` ADD `language` VARCHAR(191) NOT NULL DEFAULT 'text' COMMENT 'Paste language'")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ func PasteLangUp(tx *sql.Tx) error {
|
|||||||
func PasteLangDown(tx *sql.Tx) error {
|
func PasteLangDown(tx *sql.Tx) error {
|
||||||
_, err := tx.Exec("ALTER TABLE `pastes` DROP COLUMN `language`")
|
_, err := tx.Exec("ALTER TABLE `pastes` DROP COLUMN `language`")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import (
|
|||||||
func PrivatePastesUp(tx *sql.Tx) error {
|
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.'")
|
_, 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 {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ func PrivatePastesUp(tx *sql.Tx) error {
|
|||||||
func PrivatePastesDown(tx *sql.Tx) error {
|
func PrivatePastesDown(tx *sql.Tx) error {
|
||||||
_, err := tx.Exec("ALTER TABLE `pastes` DROP COLUMN `private`")
|
_, err := tx.Exec("ALTER TABLE `pastes` DROP COLUMN `private`")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ import (
|
|||||||
func PasswordedPastesUp(txn *sql.Tx) error {
|
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).'")
|
_, err := txn.Exec("ALTER TABLE `pastes` ADD `password` varchar(64) NOT NULL DEFAULT '' COMMENT 'Password for paste (scrypted and sha256ed).'")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err1 := txn.Exec("ALTER TABLE `pastes` ADD `password_salt` varchar(64) NOT NULL DEFAULT '' COMMENT 'Password salt (sha256ed).'")
|
_, err1 := txn.Exec("ALTER TABLE `pastes` ADD `password_salt` varchar(64) NOT NULL DEFAULT '' COMMENT 'Password salt (sha256ed).'")
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err1
|
return err1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,13 +47,13 @@ func PasswordedPastesUp(txn *sql.Tx) error {
|
|||||||
func PasswordedPastesDown(txn *sql.Tx) error {
|
func PasswordedPastesDown(txn *sql.Tx) error {
|
||||||
_, err := txn.Exec("ALTER TABLE `pastes` DROP COLUMN `password`")
|
_, err := txn.Exec("ALTER TABLE `pastes` DROP COLUMN `password`")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err1 := txn.Exec("ALTER TABLE `pastes` DROP COLUMN `password_salt`")
|
_, err1 := txn.Exec("ALTER TABLE `pastes` DROP COLUMN `password_salt`")
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err1
|
return err1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ func (db *Database) DeletePaste(pasteID int) error {
|
|||||||
|
|
||||||
_, err := db.db.Exec(db.db.Rebind("DELETE FROM pastes WHERE id=?"), pasteID)
|
_, err := db.db.Exec(db.db.Rebind("DELETE FROM pastes WHERE id=?"), pasteID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,12 +80,12 @@ func (db *Database) GetDatabaseConnection() *sql.DB {
|
|||||||
func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) {
|
func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) {
|
||||||
db.check()
|
db.check()
|
||||||
|
|
||||||
// nolint:exhaustruct
|
//nolint:exhaustruct
|
||||||
paste := &structs.Paste{}
|
paste := &structs.Paste{}
|
||||||
|
|
||||||
err := db.db.Get(paste, db.db.Rebind("SELECT * FROM `pastes` WHERE id=?"), pasteID)
|
err := db.db.Get(paste, db.db.Rebind("SELECT * FROM `pastes` WHERE id=?"), pasteID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return nil, err
|
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)
|
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 {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return nil, err
|
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)
|
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 {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lastInsertID, err1 := result.LastInsertId()
|
lastInsertID, err1 := result.LastInsertId()
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ var (
|
|||||||
|
|
||||||
func New(cc *context.Context) {
|
func New(cc *context.Context) {
|
||||||
ctx = cc
|
ctx = cc
|
||||||
// nolint:exhaustruct
|
//nolint:exhaustruct
|
||||||
dbAdapter = &Database{}
|
dbAdapter = &Database{}
|
||||||
|
|
||||||
ctx.Database.RegisterDialect(dialectinterface.Interface(Handler{}))
|
ctx.Database.RegisterDialect(dialectinterface.Interface(Handler{}))
|
||||||
|
|||||||
@@ -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.';
|
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 {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import (
|
|||||||
func PasteLangUp(tx *sql.Tx) error {
|
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';")
|
_, 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 {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ func PasteLangUp(tx *sql.Tx) error {
|
|||||||
func PasteLangDown(tx *sql.Tx) error {
|
func PasteLangDown(tx *sql.Tx) error {
|
||||||
_, err := tx.Exec("ALTER TABLE pastes DROP COLUMN language")
|
_, err := tx.Exec("ALTER TABLE pastes DROP COLUMN language")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import (
|
|||||||
func PrivatePastesUp(tx *sql.Tx) error {
|
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.';")
|
_, 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 {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ func PrivatePastesUp(tx *sql.Tx) error {
|
|||||||
func PrivatePastesDown(tx *sql.Tx) error {
|
func PrivatePastesDown(tx *sql.Tx) error {
|
||||||
_, err := tx.Exec("ALTER TABLE pastes DROP COLUMN private")
|
_, err := tx.Exec("ALTER TABLE pastes DROP COLUMN private")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ import (
|
|||||||
func PasswordedPastesUp(txn *sql.Tx) error {
|
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).';")
|
_, 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 {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
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).';")
|
_, 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 {
|
if err1 != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err1
|
return err1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,13 +47,13 @@ func PasswordedPastesUp(txn *sql.Tx) error {
|
|||||||
func PasswordedPastesDown(txn *sql.Tx) error {
|
func PasswordedPastesDown(txn *sql.Tx) error {
|
||||||
_, err := txn.Exec("ALTER TABLE pastes DROP COLUMN password")
|
_, err := txn.Exec("ALTER TABLE pastes DROP COLUMN password")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err1 := txn.Exec("ALTER TABLE pastes DROP COLUMN password_salt")
|
_, err1 := txn.Exec("ALTER TABLE pastes DROP COLUMN password_salt")
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err1
|
return err1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
package postgresql
|
package postgresql
|
||||||
|
|
||||||
// nolint:gci
|
//nolint:gci
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"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)
|
_, err := db.db.Exec(db.db.Rebind("DELETE FROM pastes WHERE id=?"), pasteID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,12 +84,12 @@ func (db *Database) GetDatabaseConnection() *sql.DB {
|
|||||||
func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) {
|
func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) {
|
||||||
db.check()
|
db.check()
|
||||||
|
|
||||||
// nolint:exhaustruct
|
//nolint:exhaustruct
|
||||||
paste := &structs.Paste{}
|
paste := &structs.Paste{}
|
||||||
|
|
||||||
err := db.db.Get(paste, db.db.Rebind("SELECT * FROM pastes WHERE id=$1"), pasteID)
|
err := db.db.Get(paste, db.db.Rebind("SELECT * FROM pastes WHERE id=$1"), pasteID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return nil, err
|
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)
|
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 {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return nil, err
|
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")
|
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 {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@ func (db *Database) SavePaste(paste *structs.Paste) (int64, error) {
|
|||||||
|
|
||||||
err = stmt.Get(&newPasteID, paste)
|
err = stmt.Get(&newPasteID, paste)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ var (
|
|||||||
// New initializes database structure.
|
// New initializes database structure.
|
||||||
func New(cc *context.Context) {
|
func New(cc *context.Context) {
|
||||||
ctx = cc
|
ctx = cc
|
||||||
// nolint:exhaustruct
|
//nolint:exhaustruct
|
||||||
dbAdapter = &Database{}
|
dbAdapter = &Database{}
|
||||||
|
|
||||||
ctx.RegisterDatabaseInterface(databaseinterface.Interface(Handler{}))
|
ctx.RegisterDatabaseInterface(databaseinterface.Interface(Handler{}))
|
||||||
|
|||||||
@@ -42,13 +42,13 @@ func CreateHTML(currentPage int, pages int, linksBase string) string {
|
|||||||
var (
|
var (
|
||||||
ellipsisStartAdded = false
|
ellipsisStartAdded = false
|
||||||
ellipsisEndAdded = false
|
ellipsisEndAdded = false
|
||||||
// nolint:varnamelen
|
//nolint:varnamelen
|
||||||
i = 2
|
i = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
for i <= pages {
|
for i <= pages {
|
||||||
// ToDo: fix it!
|
// ToDo: fix it!
|
||||||
// nolint:nestif
|
//nolint:nestif
|
||||||
if pages > 5 {
|
if pages > 5 {
|
||||||
if currentPage-3 < i && currentPage+3 > i || i == pages {
|
if currentPage-3 < i && currentPage+3 > i || i == pages {
|
||||||
paginationItemRaw := string(paginationLinkRaw)
|
paginationItemRaw := string(paginationLinkRaw)
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ type Paste struct {
|
|||||||
func (p *Paste) CreatePassword(password string) error {
|
func (p *Paste) CreatePassword(password string) error {
|
||||||
// Create salt - random string.
|
// Create salt - random string.
|
||||||
// Yes, it is insecure. Should be refactored!
|
// Yes, it is insecure. Should be refactored!
|
||||||
// nolint:gosec
|
//nolint:gosec
|
||||||
seededRand := rand.New(rand.NewSource(time.Now().UnixNano()))
|
seededRand := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
saltBytes := make([]byte, 64)
|
saltBytes := make([]byte, 64)
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ func (p *Paste) CreatePassword(password string) error {
|
|||||||
// Create crypted password and hash it.
|
// Create crypted password and hash it.
|
||||||
passwordCrypted, err := scrypt.Key([]byte(password), []byte(p.PasswordSalt), 131072, 8, 1, 64)
|
passwordCrypted, err := scrypt.Key([]byte(password), []byte(p.PasswordSalt), 131072, 8, 1, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// nolint:wrapcheck
|
//nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user