├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml └── workflows │ └── update-changelog.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── assets ├── icon-512x512.png └── screenshot.png ├── cocopasty-backend ├── Dockerfile ├── README.md ├── database.go ├── go.mod ├── go.sum ├── main.go ├── middleware.go └── utils.go ├── cocopasty-frontend ├── .dockerignore ├── Dockerfile ├── README.md ├── babel.config.js ├── entrypoint.sh ├── jsconfig.json ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── horizon-dark.min.css │ └── index.html ├── src │ ├── App.vue │ ├── main.js │ └── utils │ │ └── env.js └── vue.config.js ├── docker-compose-deploy.yml └── docker-compose.yml /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: MasterEvarior 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: MasterEvarior 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "gomod" 4 | directory: "/cocopasty-backend/" 5 | schedule: 6 | interval: "weekly" 7 | day: "friday" 8 | - package-ecosystem: "npm" 9 | directory: "/cocopasty-frontend/" 10 | schedule: 11 | interval: "daily" 12 | day: "friday" 13 | open-pull-requests-limit: 10 14 | - package-ecosystem: "docker" 15 | directory: "/cocopasty-backend" 16 | schedule: 17 | interval: "weekly" 18 | day: "friday" 19 | - package-ecosystem: "docker" 20 | directory: "/cocopasty-frontend" 21 | schedule: 22 | interval: "weekly" 23 | day: "friday" 24 | -------------------------------------------------------------------------------- /.github/workflows/update-changelog.yml: -------------------------------------------------------------------------------- 1 | name: 'Update dependencies section in changelog' 2 | on: 3 | pull_request: 4 | types: 5 | - closed 6 | 7 | jobs: 8 | changelog: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | with: 13 | token: ${{ secrets.GITHUB_TOKEN }} 14 | - uses: dangoslen/dependabot-changelog-helper@v1 15 | with: 16 | version: 'Unreleased' 17 | newVersionLineNumber: 3 18 | activationLabel: 'dependencies' 19 | changelogPath: './CHANGELOG.md' 20 | - uses: stefanzweifel/git-auto-commit-action@v4.14.1 21 | with: 22 | commit_message: "Update changelog" 23 | branch: main -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | ### Dependencies 9 | - Bumps `eslint` from 8.18.0 to 8.27.0 10 | - Bumps `core-js` from 3.23.2 to 3.25.3 11 | - Bumps `async` from 2.6.3 to 2.6.4 12 | - Bumps `node` from 14-alpine to 19-alpine 13 | - Bumps `stylus-loader` from 3.0.2 to 7.0.0 14 | - Bumps `stylus` from 0.57.0 to 0.59.0 15 | - Bumps `vue` from 3.2.31 to 3.5.13 16 | - Bumps `highlight.js` from 11.5.0 to 11.5.1 17 | - Bumps `@babel/core` from 7.17.8 to 7.20.12 18 | - Bumps `sass-loader` from 12.6.0 to 13.2.0 19 | - Bumps `@babel/eslint-parser` from 7.17.0 to 7.21.3 20 | - Bumps `eslint-plugin-vue` from 8.5.0 to 9.8.0 21 | - Bumps `@vue/cli-service` from 5.0.4 to 5.0.8 22 | - Bumps `@vue/cli-plugin-babel` from 5.0.4 to 5.0.8 23 | - Bumps `@vue/cli-plugin-eslint` from 5.0.4 to 5.0.8 24 | - Bumps `terser` from 5.12.1 to 5.14.2 25 | - Bumps `node-sass` from 7.0.1 to 8.0.0 26 | - Bumps `loader-utils` from 1.4.0 to 1.4.2 27 | - Bumps `decode-uri-component` from 0.2.0 to 0.2.2 28 | 29 | ### Changed 30 | - Stylesheet for highlight.js is now loaded locally instead from Cloudflare -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 MasterEvarior 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | logo 5 |

Cocopasty

6 | 7 |

8 | A simple copy-and-paste app to selfhost 9 |

10 | 11 | 12 | 13 |

14 | 15 | contributors 16 | 17 | 18 | last update 19 | 20 | 21 | forks 22 | 23 | 24 | stars 25 | 26 | 27 | open issues 28 | 29 | 30 | license 31 | 32 |

33 | 34 |

35 | Report Bug 36 | · 37 | Request Feature 38 |

39 |
40 | 41 |
42 | 43 | 44 | # Table of Contents 45 | 46 | - [About the Project](#about-the-project) 47 | * [Screenshots](#screenshots) 48 | * [Tech Stack](#tech-stack) 49 | * [Features](#features) 50 | - [Getting Started](#getting-started) 51 | * [Configuration](#configuration) 52 | * [Prerequisites](#prerequisites) 53 | * [Run Locally](#run-locally) 54 | * [Deployment](#deployment) 55 | - [Roadmap](#roadmap) 56 | - [Contributing](#contributing) 57 | - [FAQ](#faq) 58 | - [License](#license) 59 | - [Contact](#contact) 60 | - [Acknowledgements](#acknowledgements) 61 | 62 | 63 | 64 | ## About the Project 65 | Cocopasty is a small and simply copy-and-paste solution for your code. Paste your code in your browser and copy it on another device! 66 | 67 | 68 | ### Screenshots 69 | 70 |
71 | screenshot 72 |
73 | 74 | 75 | 76 | ### Tech Stack 77 | 78 |
79 | Client 80 | 83 |
84 | 85 |
86 | Server 87 | 90 |
91 | 92 |
93 | Database 94 | 97 |
98 | 99 |
100 | DevOps 101 | 104 |
105 | 106 | 107 | ### Features 108 | 109 | - So simple, your pet rock could use it 110 | - 150+ available languages 111 | - Autodetect languages with [highlight.js](https://highlightjs.org) 112 | - Completely dockerized 113 | 114 | ## Getting Started 115 | 116 | 117 | ### Prerequisites 118 | You need to have Go, Docker, Docker Compose and NPM installed to run/develop this project. 119 | 120 | ### Configuration 121 | Explanations for the different environment variables. Examples can be found in the docker-compose.yml files. 122 | 123 | #### Frontend 124 | - `VUE_APP_BACKEND_PORT` is the port your cocopasty-backend container runs. 125 | - `VUE_APP_BACKEND_HOST` is the host of your cocopasty-backend container. 126 | 127 | #### Backend 128 | - `LOG_LEVEL` the log level you wish to use. Default is "info". All log levels can be found [here](https://github.com/Sirupsen/logrus#level-logging). 129 | - `REDIS_HOST` is the host + port of your Redis DB. 130 | - `REDIS_PASSWORD` if your Redis instance uses password authentication, set here your password. If left empty, authentication without password will be tried. 131 | 132 | 133 | ### Run Locally 134 | 135 | Clone the project 136 | 137 | ```bash 138 | git clone https://https://github.com/MasterEvarior/cocopasty.git 139 | ``` 140 | 141 | Go to the project directory 142 | 143 | ```bash 144 | cd cocopasty 145 | ``` 146 | 147 | Run with Docker Compose 148 | 149 | ```bash 150 | docker-compose up 151 | ``` 152 | 153 | 154 | ### Deployment 155 | 156 | #### Docker Compose 157 | To deploy this project copy the contents of the [docker-compose-deploy.yml](https://github.com/MasterEvarior/cocopasty/blob/main/docker-compose-deploy.yml) file and paste it into a new file. 158 | 159 | ```bash 160 | wget https://raw.githubusercontent.com/MasterEvarior/cocopasty/main/docker-compose-deploy.yml 161 | ``` 162 | Change the ports, volumes, etc. to your liking. 163 | ```bash 164 | vi docker-compose-deploy.yml 165 | ``` 166 | 167 | Rename the file and run it with Docker Compose. 168 | ```bash 169 | mv docker-compose-deploy.yml docker-compose.yml 170 | docker-compose up 171 | ``` 172 | 173 | ## Roadmap 174 | Feel free to suggest features through a GitHub issue, in addition to the ones listed below: 175 | - [ ] Backend tests 176 | - [ ] Frontend tests 177 | - [ ] Installation instructions for Unraid 178 | - [ ] CI/CD with GitHub-Actions 179 | - [X] Automatically update Changelog for dependency updates 180 | - [ ] Automatic releases 181 | - [ ] Run tests 182 | 183 | 184 | ## Contributing 185 | Contributions are always welcome! 186 | 187 | 188 | ## FAQ 189 | 190 | - Is there an official method to install WITHOUT Docker? 191 | 192 | + No 193 | 194 | - Is there any sort of build in authentication? 195 | 196 | + No, though you could use something like [Authelia](https://www.authelia.com/docs/) 197 | 198 | - Can I use this to copy my API-Keys etc. from one device to another? 199 | 200 | + You can but I'd strongly advise against it 201 | 202 | - Which languages are available for auto-highligting? 203 | 204 | + A complete list can be found [here](https://highlightjs.readthedocs.io/en/latest/supported-languages.html) 205 | 206 | - Can I use this with my already existing Redis instance? 207 | 208 | + Sure, you just have to adjust the compose file to your liking 209 | 210 | - Does the default compose file configure Redis to be persistent? 211 | 212 | + No 213 | 214 | 215 | ## License 216 | 217 | Distributed under the MIT License. See the LICENSE file for more information. 218 | 219 | 220 | ## Contact 221 | 222 | Email: contact@giannin.dev 223 | 224 | Project Link: [https://github.com/MasterEvarior/cocopasty](https://github.com/MasterEvarior/cocopasty) 225 | 226 | 227 | 228 | ## Acknowledgements 229 | 230 | Cool projects which make Cocopasty possible 231 | 232 | - [Shields.io](https://shields.io/) 233 | - [Awesome Readme Template](https://github.com/Louis3797/awesome-readme-template) 234 | - [highlight.js](https://highlightjs.org) 235 | - [Vue Prism Editor](https://github.com/koca/vue-prism-editor) 236 | - [Guide to Vue.js + Docker env variables](https://medium.com/js-dojo/vue-js-runtime-environment-variables-807fa8f68665) 237 | - [CSS Button Generator](https://www.bestcssbuttongenerator.com) 238 | -------------------------------------------------------------------------------- /assets/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MasterEvarior/cocopasty/554a44b16abc74b3cba13fb4d38a751795f5f33c/assets/icon-512x512.png -------------------------------------------------------------------------------- /assets/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MasterEvarior/cocopasty/554a44b16abc74b3cba13fb4d38a751795f5f33c/assets/screenshot.png -------------------------------------------------------------------------------- /cocopasty-backend/Dockerfile: -------------------------------------------------------------------------------- 1 | # develop stage 2 | FROM golang:alpine as develop-stage 3 | RUN apk add --no-cache git 4 | RUN mkdir /app 5 | ADD . /app 6 | WORKDIR /app 7 | 8 | # build stage 9 | FROM develop-stage as build-stage 10 | RUN go build -o cocopasty-backend . 11 | 12 | # production stage 13 | FROM golang:alpine as production-stage 14 | COPY --from=build-stage /app/cocopasty-backend /app/cocopasty-backend 15 | CMD ["/app/cocopasty-backend"] -------------------------------------------------------------------------------- /cocopasty-backend/README.md: -------------------------------------------------------------------------------- 1 | # Cocopasty Backend 2 | 3 | ## Project setup 4 | ``` 5 | go run main.go 6 | ``` 7 | 8 | ### Compiles and minifies for production 9 | ``` 10 | go build -o cocopasty-backend . 11 | ``` 12 | 13 | ## Docker 14 | Build container locally 15 | ``` 16 | docker build -t cocopasty-backend . 17 | ``` -------------------------------------------------------------------------------- /cocopasty-backend/database.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "os" 6 | 7 | "github.com/go-redis/redis/v8" 8 | log "github.com/sirupsen/logrus" 9 | ) 10 | 11 | type database struct { 12 | connection *redis.Client 13 | } 14 | 15 | const keyName = "cocopasty-code-snippet" 16 | 17 | func CreateDatabaseClient() (*database, error) { 18 | setLogLevel() 19 | log.Debug("Creating connection to Redis...") 20 | 21 | redisConnection := redis.NewClient(&redis.Options{ 22 | Network: "tcp", 23 | Addr: getAddress(), 24 | Password: getPassword(), 25 | DB: 0, 26 | }) 27 | 28 | return &database{ 29 | connection: redisConnection, 30 | }, redisConnection.Ping(context.Background()).Err() 31 | } 32 | 33 | func (d *database) CreateEntry(ctx context.Context, code string) error { 34 | log.Debug("Setting value in Redis") 35 | status := d.connection.Set(ctx, keyName, code, 0) 36 | 37 | return status.Err() 38 | } 39 | 40 | func (d *database) ReadEntry(ctx context.Context) (string, error) { 41 | log.Debug("Getting value from Redis") 42 | 43 | return d.connection.Get(ctx, keyName).Result() 44 | } 45 | 46 | func getAddress() string { 47 | input := os.Getenv("REDIS_HOST") 48 | log.Info("REDIS_HOST: ", input) 49 | 50 | return input 51 | } 52 | 53 | func getPassword() string { 54 | input := os.Getenv("REDIS_PASSWORD") 55 | if input == "" { 56 | log.Info("No Redis password was set") 57 | } else { 58 | log.Info("A Redis password was set") 59 | } 60 | 61 | return input 62 | } 63 | -------------------------------------------------------------------------------- /cocopasty-backend/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/MasterEvariour/cocopasty/cocopasty-backend 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/gorilla/mux v1.8.0 7 | github.com/rs/cors v1.8.3 8 | ) 9 | 10 | require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect 11 | 12 | require ( 13 | github.com/cespare/xxhash/v2 v2.1.2 // indirect 14 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect 15 | github.com/go-redis/redis/v8 v8.11.5 16 | github.com/sirupsen/logrus v1.9.0 17 | ) 18 | -------------------------------------------------------------------------------- /cocopasty-backend/go.sum: -------------------------------------------------------------------------------- 1 | github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= 2 | github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 3 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 5 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 6 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= 7 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= 8 | github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= 9 | github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= 10 | github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= 11 | github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= 12 | github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 13 | github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= 14 | github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= 15 | github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= 16 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 17 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 18 | github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= 19 | github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= 20 | github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= 21 | github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 22 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 23 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 24 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 25 | golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= 26 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= 27 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 28 | golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= 29 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 30 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 31 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 32 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 33 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 34 | -------------------------------------------------------------------------------- /cocopasty-backend/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | 7 | "github.com/gorilla/mux" 8 | "github.com/rs/cors" 9 | log "github.com/sirupsen/logrus" 10 | ) 11 | 12 | type CodeSnippet struct { 13 | Code string `json:"Code"` 14 | } 15 | 16 | var databaseClient *database 17 | 18 | func main() { 19 | setLogLevel() 20 | //Initialize router 21 | log.Info("Starting Cocopasty...") 22 | router := mux.NewRouter() 23 | 24 | router.Use(LoggingMiddleware) 25 | 26 | router.HandleFunc("/", handleGets).Methods("GET") 27 | router.HandleFunc("/", handlePosts).Methods("POST") 28 | 29 | corsHandler := cors.Default().Handler(router) 30 | 31 | //Create database connection 32 | var err error 33 | databaseClient, err = CreateDatabaseClient() 34 | 35 | if err != nil { 36 | log.Panic("Could not connect to database, shutting down application...") 37 | panic(err) 38 | } 39 | 40 | log.Info("Connection to Redis was successfull") 41 | 42 | //Start server 43 | log.Info("Starting web server...") 44 | err = http.ListenAndServe(":8080", corsHandler) 45 | if err != nil { 46 | log.Fatal(err) 47 | } 48 | log.Info("Cocopasty is started and ready!") 49 | } 50 | 51 | func handlePosts(w http.ResponseWriter, r *http.Request) { 52 | ctx := r.Context() 53 | 54 | contentType := r.Header.Get("Content-Type") 55 | if contentType != "application/json" { 56 | log.Debug("Invalid content type, returning 400") 57 | w.WriteHeader(http.StatusBadRequest) 58 | return 59 | } 60 | 61 | var newSnippet CodeSnippet 62 | 63 | err := json.NewDecoder(r.Body).Decode(&newSnippet) 64 | if err != nil { 65 | log.Errorf("Could not decode JSON: ", err) 66 | w.WriteHeader(http.StatusBadRequest) 67 | return 68 | } 69 | 70 | err = databaseClient.CreateEntry(ctx, newSnippet.Code) 71 | if err != nil { 72 | log.Errorf("Failed to save snippet in Redis: ", err) 73 | w.WriteHeader(http.StatusInternalServerError) 74 | return 75 | } 76 | } 77 | 78 | func handleGets(w http.ResponseWriter, r *http.Request) { 79 | ctx := r.Context() 80 | 81 | w.Header().Set("Content-Type", "application/json") 82 | w.WriteHeader(http.StatusOK) 83 | 84 | value, err := databaseClient.ReadEntry(ctx) 85 | 86 | if err != nil { 87 | log.Error("Could not retrieve snippet from Redis: ", err) 88 | w.WriteHeader(http.StatusInternalServerError) 89 | return 90 | } 91 | 92 | log.Debug("GET-Request successfull, returning 200") 93 | json.NewEncoder(w).Encode(CodeSnippet{value}) 94 | } 95 | -------------------------------------------------------------------------------- /cocopasty-backend/middleware.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | log "github.com/sirupsen/logrus" 7 | ) 8 | 9 | func LoggingMiddleware(next http.Handler) http.Handler { 10 | return http.HandlerFunc( 11 | func(w http.ResponseWriter, r *http.Request) { 12 | log.Debugf("Incoming request: \n Method: '%s' \n URI: '%s'", r.Method, r.RequestURI) 13 | next.ServeHTTP(w, r) 14 | }, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /cocopasty-backend/utils.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | log "github.com/sirupsen/logrus" 7 | ) 8 | 9 | func setLogLevel() { 10 | defer log.Info("Log level to ", log.GetLevel()) 11 | input := os.Getenv("LOG_LEVEL") 12 | 13 | parsedLevel, err := log.ParseLevel(input) 14 | 15 | if err != nil { 16 | log.Error(err) 17 | return 18 | } 19 | 20 | log.SetLevel(parsedLevel) 21 | } 22 | -------------------------------------------------------------------------------- /cocopasty-frontend/.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .DS_Store 3 | node_modules 4 | dist -------------------------------------------------------------------------------- /cocopasty-frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | # develop stage 2 | FROM node:19-alpine as develop-stage 3 | WORKDIR /app 4 | COPY package*.json ./ 5 | RUN npm install 6 | COPY . . 7 | 8 | # build stage 9 | FROM develop-stage as build-stage 10 | RUN npm run build 11 | 12 | # production stage 13 | FROM nginx:alpine as production-stage 14 | COPY --from=build-stage /app/dist /usr/share/nginx/html 15 | COPY entrypoint.sh /usr/share/nginx/ 16 | ENTRYPOINT ["/usr/share/nginx/entrypoint.sh"] 17 | EXPOSE 90 18 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /cocopasty-frontend/README.md: -------------------------------------------------------------------------------- 1 | # Cocopasty Frontend 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | npm run lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | 26 | ## Docker 27 | Build container locally 28 | ``` 29 | docker build -t cocopasty-frontend . 30 | ``` 31 | -------------------------------------------------------------------------------- /cocopasty-frontend/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /cocopasty-frontend/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | JSON_STRING='window.configs = { \ 3 | "VUE_APP_BACKEND_PORT":"'"${VUE_APP_BACKEND_PORT}"'", \ 4 | "VUE_APP_BACKEND_HOST":"'"${VUE_APP_BACKEND_HOST}"'" \ 5 | }' 6 | sed -i "s@// CONFIGURATION_PLACEHOLDER@${JSON_STRING}@" /usr/share/nginx/html/index.html 7 | exec "$@" -------------------------------------------------------------------------------- /cocopasty-frontend/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "esnext", 5 | "baseUrl": "./", 6 | "moduleResolution": "node", 7 | "paths": { 8 | "@/*": [ 9 | "src/*" 10 | ] 11 | }, 12 | "lib": [ 13 | "esnext", 14 | "dom", 15 | "dom.iterable", 16 | "scripthost" 17 | ] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /cocopasty-frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cocopasty-frontend", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "@beyonk/google-fonts-webpack-plugin": "^1.7.0", 12 | "@meforma/vue-toaster": "^1.3.0", 13 | "core-js": "^3.27.1", 14 | "highlight.js": "^11.7.0", 15 | "stylus": "^0.59.0", 16 | "stylus-loader": "^7.1.0", 17 | "vue": "^3.2.45", 18 | "vue-prism-editor": "^2.0.0-alpha.2" 19 | }, 20 | "devDependencies": { 21 | "@babel/core": "^7.20.2", 22 | "@babel/eslint-parser": "^7.19.1", 23 | "@vue/cli-plugin-babel": "~5.0.8", 24 | "@vue/cli-plugin-eslint": "~5.0.8", 25 | "@vue/cli-service": "~5.0.8", 26 | "eslint": "^8.31.0", 27 | "eslint-plugin-vue": "^9.8.0", 28 | "node-sass": "^8.0.0", 29 | "sass-loader": "^13.2.0" 30 | }, 31 | "eslintConfig": { 32 | "root": true, 33 | "env": { 34 | "node": true 35 | }, 36 | "extends": [ 37 | "plugin:vue/vue3-essential", 38 | "eslint:recommended" 39 | ], 40 | "parserOptions": { 41 | "parser": "@babel/eslint-parser" 42 | }, 43 | "rules": {} 44 | }, 45 | "browserslist": [ 46 | "> 1%", 47 | "last 2 versions", 48 | "not dead", 49 | "not ie 11" 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /cocopasty-frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MasterEvarior/cocopasty/554a44b16abc74b3cba13fb4d38a751795f5f33c/cocopasty-frontend/public/favicon.ico -------------------------------------------------------------------------------- /cocopasty-frontend/public/horizon-dark.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | Theme: Horizon Dark 3 | Author: Michaël Ball (http://github.com/michael-ball/) 4 | License: ~ MIT (or more permissive) [via base16-schemes-source] 5 | Maintainer: @highlightjs/core-team 6 | Version: 2021.09.0 7 | */pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#cbced0;background:#1c1e26}.hljs ::selection,.hljs::selection{background-color:#2e303e;color:#cbced0}.hljs-comment{color:#6f6f70}.hljs-tag{color:#9da0a2}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#cbced0}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#e93c58}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#e58d7d}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#efb993}.hljs-strong{font-weight:700;color:#efb993}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#efaf8e}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#24a8b4}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#df5273}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#b072d1}.hljs-emphasis{color:#b072d1;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#e4a382}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700} -------------------------------------------------------------------------------- /cocopasty-frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | Cocopasty 13 | 14 | 15 | 18 |
19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /cocopasty-frontend/src/App.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 104 | 105 | -------------------------------------------------------------------------------- /cocopasty-frontend/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import Toaster from '@meforma/vue-toaster'; 3 | import App from './App.vue' 4 | 5 | let app = createApp(App) 6 | 7 | app 8 | .use(Toaster) 9 | .mount('#app') 10 | -------------------------------------------------------------------------------- /cocopasty-frontend/src/utils/env.js: -------------------------------------------------------------------------------- 1 | export default function getEnv(name) { 2 | return window?.configs?.[name] || process.env[name] 3 | } -------------------------------------------------------------------------------- /cocopasty-frontend/vue.config.js: -------------------------------------------------------------------------------- 1 | const { defineConfig } = require('@vue/cli-service') 2 | const GoogleFontsPlugin = require("@beyonk/google-fonts-webpack-plugin") 3 | 4 | // vue.config.js 5 | module.exports = { 6 | } 7 | module.exports = defineConfig({ 8 | transpileDependencies: true, 9 | configureWebpack: { 10 | plugins: [ 11 | new GoogleFontsPlugin({ 12 | fonts: [ 13 | { family: "Roboto Mono", variants: [ "500", "700" ] } 14 | ] 15 | }) 16 | ]} 17 | }) 18 | -------------------------------------------------------------------------------- /docker-compose-deploy.yml: -------------------------------------------------------------------------------- 1 | services: 2 | frontend: 3 | image: masterevarior/cocopasty-frontend:1.0.0 4 | ports: 5 | - "8080:80" 6 | environment: 7 | VUE_APP_BACKEND_PORT: 8081 8 | VUE_APP_BACKEND_HOST: "http://localhost" 9 | depends_on: 10 | - backend 11 | backend: 12 | image: masterevarior/cocopasty-backend:1.2.1 13 | ports: 14 | - "8081:8080" 15 | environment: 16 | LOG_LEVEL: "info" 17 | REDIS_HOST: "redis:6379" 18 | # REDIS_PASSWORD: "your_password" 19 | depends_on: 20 | - redis 21 | redis: 22 | image: "redis:alpine" 23 | ports: 24 | - "6379:6379" -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | frontend: 3 | build: ./cocopasty-frontend 4 | ports: 5 | - "8080:80" 6 | environment: 7 | VUE_APP_BACKEND_PORT: 8081 8 | VUE_APP_BACKEND_HOST: "http://localhost" 9 | depends_on: 10 | - backend 11 | backend: 12 | build: ./cocopasty-backend 13 | ports: 14 | - "8081:8080" 15 | environment: 16 | LOG_LEVEL: "debug" 17 | REDIS_HOST: "redis:6379" 18 | # REDIS_PASSWORD: "123" currently not used 19 | depends_on: 20 | - redis 21 | redis: 22 | image: "redis:alpine" 23 | ports: 24 | - "6379:6379" --------------------------------------------------------------------------------