├── .circleci ├── config.yml ├── test-run.sh └── test-setup.sh ├── .gitattributes ├── .gitignore ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── addons ├── README.md └── github.com │ └── bosssauce │ └── reference │ ├── LICENSE │ ├── README.md │ └── reference.go ├── cmd └── ponzu │ ├── LICENSE │ ├── add.go │ ├── build.go │ ├── cli_test.go │ ├── generate.go │ ├── main.go │ ├── new.go │ ├── new_test.go │ ├── options.go │ ├── paths.go │ ├── ponzu.json │ ├── templates │ ├── gen-checkbox.tmpl │ ├── gen-content.tmpl │ ├── gen-custom.tmpl │ ├── gen-file-repeater.tmpl │ ├── gen-file.tmpl │ ├── gen-hidden.tmpl │ ├── gen-input-repeater.tmpl │ ├── gen-input.tmpl │ ├── gen-reference-repeater.tmpl │ ├── gen-reference.tmpl │ ├── gen-richtext.tmpl │ ├── gen-select-repeater.tmpl │ ├── gen-select.tmpl │ ├── gen-tags.tmpl │ └── gen-textarea.tmpl │ ├── upgrade.go │ ├── usage.go │ ├── vendor │ ├── github.com │ │ ├── boltdb │ │ │ └── bolt │ │ │ │ ├── .gitignore │ │ │ │ ├── LICENSE │ │ │ │ ├── Makefile │ │ │ │ ├── README.md │ │ │ │ ├── appveyor.yml │ │ │ │ ├── bolt_386.go │ │ │ │ ├── bolt_amd64.go │ │ │ │ ├── bolt_arm.go │ │ │ │ ├── bolt_arm64.go │ │ │ │ ├── bolt_linux.go │ │ │ │ ├── bolt_openbsd.go │ │ │ │ ├── bolt_ppc.go │ │ │ │ ├── bolt_ppc64.go │ │ │ │ ├── bolt_ppc64le.go │ │ │ │ ├── bolt_s390x.go │ │ │ │ ├── bolt_unix.go │ │ │ │ ├── bolt_unix_solaris.go │ │ │ │ ├── bolt_windows.go │ │ │ │ ├── boltsync_unix.go │ │ │ │ ├── bucket.go │ │ │ │ ├── bucket_test.go │ │ │ │ ├── cmd │ │ │ │ └── bolt │ │ │ │ │ ├── main.go │ │ │ │ │ └── main_test.go │ │ │ │ ├── cursor.go │ │ │ │ ├── cursor_test.go │ │ │ │ ├── db.go │ │ │ │ ├── db_test.go │ │ │ │ ├── doc.go │ │ │ │ ├── errors.go │ │ │ │ ├── freelist.go │ │ │ │ ├── freelist_test.go │ │ │ │ ├── node.go │ │ │ │ ├── node_test.go │ │ │ │ ├── page.go │ │ │ │ ├── page_test.go │ │ │ │ ├── quick_test.go │ │ │ │ ├── simulation_test.go │ │ │ │ ├── tx.go │ │ │ │ └── tx_test.go │ │ ├── gofrs │ │ │ └── uuid │ │ │ │ ├── .gitignore │ │ │ │ ├── .travis.yml │ │ │ │ ├── LICENSE │ │ │ │ ├── README.md │ │ │ │ ├── codec.go │ │ │ │ ├── codec_test.go │ │ │ │ ├── fuzz.go │ │ │ │ ├── generator.go │ │ │ │ ├── generator_test.go │ │ │ │ ├── sql.go │ │ │ │ ├── sql_test.go │ │ │ │ ├── testdata │ │ │ │ └── corpus │ │ │ │ │ ├── 1416586f4a34d02bcb506f6107b40df512b9f2f9 │ │ │ │ │ ├── 3b46a7e7b02ec193581e6c9fa2c8a72f50a64e08-1 │ │ │ │ │ ├── 50c54bb75fcfdc488f162bf2f0c6dec6103bfa18-5 │ │ │ │ │ ├── 69c581ab749cbd56be8684d3a58ac2cfab9af0f4-5 │ │ │ │ │ ├── 752bf000e0bff06777dd0d6f0be6353844de678a-3 │ │ │ │ │ ├── a4483762d4ece8466d82cca5cacd35a0829c4e60-2 │ │ │ │ │ ├── d0952c45e0c823fc5cc12bcf7d9b877d150ab523-1 │ │ │ │ │ ├── da39a3ee5e6b4b0d3255bfef95601890afd80709 │ │ │ │ │ ├── e2b84d2065846891f18ae109b12e01d224e1c7c3-4 │ │ │ │ │ ├── e320d749435115e874f77420e17d0937e07f69f3-2 │ │ │ │ │ ├── ed132d47d757f6468443a22df8a2a965efb34098-7 │ │ │ │ │ ├── eeefb01f7bb3c627aedb292c994b20f739ffd613-6 │ │ │ │ │ ├── seed_invalid_0 │ │ │ │ │ ├── seed_invalid_1 │ │ │ │ │ ├── seed_invalid_10 │ │ │ │ │ ├── seed_invalid_11 │ │ │ │ │ ├── seed_invalid_12 │ │ │ │ │ ├── seed_invalid_13 │ │ │ │ │ ├── seed_invalid_14 │ │ │ │ │ ├── seed_invalid_15 │ │ │ │ │ ├── seed_invalid_16 │ │ │ │ │ ├── seed_invalid_17 │ │ │ │ │ ├── seed_invalid_18 │ │ │ │ │ ├── seed_invalid_19 │ │ │ │ │ ├── seed_invalid_2 │ │ │ │ │ ├── seed_invalid_20 │ │ │ │ │ ├── seed_invalid_21 │ │ │ │ │ ├── seed_invalid_22 │ │ │ │ │ ├── seed_invalid_23 │ │ │ │ │ ├── seed_invalid_3 │ │ │ │ │ ├── seed_invalid_4 │ │ │ │ │ ├── seed_invalid_5 │ │ │ │ │ ├── seed_invalid_6 │ │ │ │ │ ├── seed_invalid_7 │ │ │ │ │ ├── seed_invalid_8 │ │ │ │ │ ├── seed_invalid_9 │ │ │ │ │ ├── seed_valid_BracedCanonical │ │ │ │ │ ├── seed_valid_BracedHashlike │ │ │ │ │ ├── seed_valid_Canonical │ │ │ │ │ ├── seed_valid_Hashlike │ │ │ │ │ ├── seed_valid_URNCanonical │ │ │ │ │ └── seed_valid_URNHashlike │ │ │ │ ├── uuid.go │ │ │ │ └── uuid_test.go │ │ ├── gorilla │ │ │ └── schema │ │ │ │ ├── .travis.yml │ │ │ │ ├── LICENSE │ │ │ │ ├── README.md │ │ │ │ ├── cache.go │ │ │ │ ├── converter.go │ │ │ │ ├── decoder.go │ │ │ │ ├── decoder_test.go │ │ │ │ └── doc.go │ │ ├── nilslice │ │ │ ├── email │ │ │ │ ├── LICENSE │ │ │ │ ├── README.md │ │ │ │ ├── email.go │ │ │ │ └── email_test.go │ │ │ └── jwt │ │ │ │ ├── LICENSE │ │ │ │ ├── README.md │ │ │ │ ├── doc.go │ │ │ │ └── jwt.go │ │ ├── spf13 │ │ │ ├── cobra │ │ │ │ ├── .mailmap │ │ │ │ ├── LICENSE.txt │ │ │ │ ├── README.md │ │ │ │ ├── cobra.go │ │ │ │ ├── cobra_test.go │ │ │ │ ├── command.go │ │ │ │ ├── command_notwin.go │ │ │ │ ├── command_test.go │ │ │ │ └── command_win.go │ │ │ └── pflag │ │ │ │ ├── LICENSE │ │ │ │ ├── README.md │ │ │ │ ├── bool.go │ │ │ │ ├── bool_slice.go │ │ │ │ ├── bool_slice_test.go │ │ │ │ ├── bool_test.go │ │ │ │ ├── count.go │ │ │ │ ├── count_test.go │ │ │ │ ├── duration.go │ │ │ │ ├── example_test.go │ │ │ │ ├── export_test.go │ │ │ │ ├── flag.go │ │ │ │ ├── flag_test.go │ │ │ │ ├── float32.go │ │ │ │ ├── float64.go │ │ │ │ ├── golangflag.go │ │ │ │ ├── golangflag_test.go │ │ │ │ ├── int.go │ │ │ │ ├── int32.go │ │ │ │ ├── int64.go │ │ │ │ ├── int8.go │ │ │ │ ├── int_slice.go │ │ │ │ ├── int_slice_test.go │ │ │ │ ├── ip.go │ │ │ │ ├── ip_slice.go │ │ │ │ ├── ip_slice_test.go │ │ │ │ ├── ip_test.go │ │ │ │ ├── ipmask.go │ │ │ │ ├── ipnet.go │ │ │ │ ├── ipnet_test.go │ │ │ │ ├── string.go │ │ │ │ ├── string_array.go │ │ │ │ ├── string_array_test.go │ │ │ │ ├── string_slice.go │ │ │ │ ├── string_slice_test.go │ │ │ │ ├── uint.go │ │ │ │ ├── uint16.go │ │ │ │ ├── uint32.go │ │ │ │ ├── uint64.go │ │ │ │ ├── uint8.go │ │ │ │ ├── uint_slice.go │ │ │ │ └── uint_slice_test.go │ │ └── tidwall │ │ │ ├── gjson │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── gjson.go │ │ │ └── logo.png │ │ │ └── sjson │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── logo.png │ │ │ └── sjson.go │ └── golang.org │ │ └── x │ │ ├── crypto │ │ ├── autocert │ │ │ ├── autocert.go │ │ │ ├── autocert_test.go │ │ │ ├── cache.go │ │ │ ├── cache_test.go │ │ │ ├── example_test.go │ │ │ ├── listener.go │ │ │ ├── renewal.go │ │ │ └── renewal_test.go │ │ └── bcrypt │ │ │ ├── base64.go │ │ │ ├── bcrypt.go │ │ │ └── bcrypt_test.go │ │ ├── net │ │ └── context │ │ │ ├── context.go │ │ │ ├── context_test.go │ │ │ ├── ctxhttp │ │ │ ├── ctxhttp.go │ │ │ ├── ctxhttp_17_test.go │ │ │ ├── ctxhttp_pre17.go │ │ │ ├── ctxhttp_pre17_test.go │ │ │ └── ctxhttp_test.go │ │ │ ├── go17.go │ │ │ ├── pre_go17.go │ │ │ └── withtimeout_test.go │ │ └── text │ │ ├── transform │ │ ├── examples_test.go │ │ ├── transform.go │ │ └── transform_test.go │ │ └── unicode │ │ └── norm │ │ ├── composition.go │ │ ├── composition_test.go │ │ ├── example_iter_test.go │ │ ├── example_test.go │ │ ├── forminfo.go │ │ ├── forminfo_test.go │ │ ├── input.go │ │ ├── iter.go │ │ ├── iter_test.go │ │ ├── maketables.go │ │ ├── norm_test.go │ │ ├── normalize.go │ │ ├── normalize_test.go │ │ ├── readwriter.go │ │ ├── readwriter_test.go │ │ ├── tables.go │ │ ├── transform.go │ │ ├── transform_test.go │ │ ├── trie.go │ │ ├── triegen.go │ │ └── ucd_test.go │ └── version.go ├── content └── doc.go ├── deployment ├── README.md └── sysv │ └── ponzu-server ├── docs ├── .gitignore ├── LICENSE ├── README.md ├── build │ ├── 404.html │ ├── CLI │ │ ├── General-Usage │ │ │ └── index.html │ │ └── Generating-References │ │ │ └── index.html │ ├── Content │ │ ├── An-Overview │ │ │ └── index.html │ │ └── Extending-Content │ │ │ └── index.html │ ├── Form-Fields │ │ └── HTML-Inputs │ │ │ └── index.html │ ├── HTTP-APIs │ │ ├── Content │ │ │ └── index.html │ │ ├── File-Metadata │ │ │ └── index.html │ │ └── Search │ │ │ └── index.html │ ├── Interfaces │ │ ├── API │ │ │ └── index.html │ │ ├── Editor │ │ │ └── index.html │ │ ├── Format │ │ │ └── index.html │ │ ├── Item │ │ │ └── index.html │ │ └── Search │ │ │ └── index.html │ ├── Ponzu-Addons │ │ ├── Creating-Addons │ │ │ └── index.html │ │ └── Using-Addons │ │ │ └── index.html │ ├── Quickstart │ │ └── Overview │ │ │ └── index.html │ ├── References │ │ └── Overview │ │ │ └── index.html │ ├── Running-Backups │ │ └── Backups │ │ │ └── index.html │ ├── System-Configuration │ │ └── Settings │ │ │ └── index.html │ ├── System-Deployment │ │ ├── Docker │ │ │ └── index.html │ │ └── SysV-Style │ │ │ └── index.html │ ├── assets │ │ ├── images │ │ │ ├── favicon.ico │ │ │ └── icons │ │ │ │ ├── bitbucket-670608a71a.svg │ │ │ │ ├── github-1da075986e.svg │ │ │ │ └── gitlab-5ad3f9f9e5.svg │ │ ├── javascripts │ │ │ ├── application-6b599127bc.js │ │ │ └── modernizr-56ade86843.js │ │ └── stylesheets │ │ │ ├── application-4d0d3f2fbf.css │ │ │ └── application-f78e5cb881.palette.css │ ├── images │ │ ├── editor-checkbox.png │ │ ├── editor-file-repeater.png │ │ ├── editor-file.png │ │ ├── editor-input-repeater.png │ │ ├── editor-input.png │ │ ├── editor-richtext.png │ │ ├── editor-select-repeater.png │ │ ├── editor-select.png │ │ ├── editor-tags.png │ │ ├── editor-textarea.png │ │ ├── logo.png │ │ └── ponzu-banner.png │ ├── index.html │ ├── mkdocs │ │ ├── js │ │ │ ├── lunr.min.js │ │ │ ├── mustache.min.js │ │ │ ├── require.js │ │ │ ├── search-results-template.mustache │ │ │ ├── search.js │ │ │ └── text.js │ │ └── search_index.json │ └── sitemap.xml ├── mkdocs.yml └── src │ ├── CLI │ ├── General-Usage.md │ └── Generating-References.md │ ├── Content │ ├── An-Overview.md │ └── Extending-Content.md │ ├── Form-Fields │ └── HTML-Inputs.md │ ├── HTTP-APIs │ ├── Content.md │ ├── File-Metadata.md │ └── Search.md │ ├── Interfaces │ ├── API.md │ ├── Editor.md │ ├── Format.md │ ├── Item.md │ └── Search.md │ ├── Ponzu-Addons │ ├── Creating-Addons.md │ └── Using-Addons.md │ ├── Quickstart │ └── Overview.md │ ├── References │ └── Overview.md │ ├── Running-Backups │ └── Backups.md │ ├── System-Configuration │ └── Settings.md │ ├── System-Deployment │ ├── Docker.md │ └── SysV-Style.md │ ├── images │ ├── editor-checkbox.png │ ├── editor-file-repeater.png │ ├── editor-file.png │ ├── editor-input-repeater.png │ ├── editor-input.png │ ├── editor-richtext.png │ ├── editor-select-repeater.png │ ├── editor-select.png │ ├── editor-tags.png │ ├── editor-textarea.png │ ├── logo.png │ └── ponzu-banner.png │ └── index.md ├── examples ├── LICENSE ├── README.md ├── createable │ ├── README.md │ └── content │ │ └── song.go ├── deleteable │ ├── README.md │ └── content │ │ └── song.go └── updateable │ ├── README.md │ └── content │ └── song.go ├── management ├── editor │ ├── dom.go │ ├── editor.go │ ├── elements.go │ ├── repeaters.go │ └── values.go ├── format │ └── csv.go └── manager │ └── manager.go ├── ponzu-banner.png └── system ├── addon ├── addon.go ├── api.go └── manager.go ├── admin ├── admin.go ├── config │ └── config.go ├── export.go ├── filesystem.go ├── handlers.go ├── server.go ├── static │ ├── common │ │ └── js │ │ │ ├── jquery-2.1.4.min.js │ │ │ └── util.js │ ├── dashboard │ │ ├── css │ │ │ ├── admin.css │ │ │ ├── material-icons.css │ │ │ └── materialize.min.css │ │ ├── fonts │ │ │ ├── icons-regular.woff2 │ │ │ └── roboto │ │ │ │ ├── Roboto-Bold.eot │ │ │ │ ├── Roboto-Bold.ttf │ │ │ │ ├── Roboto-Bold.woff │ │ │ │ ├── Roboto-Bold.woff2 │ │ │ │ ├── Roboto-Light.eot │ │ │ │ ├── Roboto-Light.ttf │ │ │ │ ├── Roboto-Light.woff │ │ │ │ ├── Roboto-Light.woff2 │ │ │ │ ├── Roboto-Medium.eot │ │ │ │ ├── Roboto-Medium.ttf │ │ │ │ ├── Roboto-Medium.woff │ │ │ │ ├── Roboto-Medium.woff2 │ │ │ │ ├── Roboto-Regular.eot │ │ │ │ ├── Roboto-Regular.ttf │ │ │ │ ├── Roboto-Regular.woff │ │ │ │ ├── Roboto-Regular.woff2 │ │ │ │ ├── Roboto-Thin.eot │ │ │ │ ├── Roboto-Thin.ttf │ │ │ │ ├── Roboto-Thin.woff │ │ │ │ └── Roboto-Thin.woff2 │ │ ├── img │ │ │ └── ponzu-file.png │ │ └── js │ │ │ ├── chart.bundle.min.js │ │ │ └── materialize.min.js │ └── editor │ │ ├── css │ │ ├── materialNote.css │ │ └── materialNote.css.map │ │ ├── font │ │ └── roboto │ │ │ ├── Roboto-Bold.ttf │ │ │ ├── Roboto-Bold.woff │ │ │ ├── Roboto-Bold.woff2 │ │ │ ├── Roboto-Light.ttf │ │ │ ├── Roboto-Light.woff │ │ │ ├── Roboto-Light.woff2 │ │ │ ├── Roboto-Medium.ttf │ │ │ ├── Roboto-Medium.woff │ │ │ ├── Roboto-Medium.woff2 │ │ │ ├── Roboto-Regular.ttf │ │ │ ├── Roboto-Regular.woff │ │ │ ├── Roboto-Regular.woff2 │ │ │ ├── Roboto-Thin.ttf │ │ │ ├── Roboto-Thin.woff │ │ │ └── Roboto-Thin.woff2 │ │ ├── js │ │ ├── ckMaterializeOverrides.js │ │ └── materialNote.js │ │ ├── license.txt │ │ └── sass │ │ ├── components │ │ ├── _buttons.scss │ │ ├── _cards.scss │ │ ├── _collapsible.scss │ │ ├── _color.scss │ │ ├── _dropdown.scss │ │ ├── _form.scss │ │ ├── _global.scss │ │ ├── _grid.scss │ │ ├── _icons-material-design.scss │ │ ├── _materialbox.scss │ │ ├── _mixins.scss │ │ ├── _modal.scss │ │ ├── _navbar.scss │ │ ├── _normalize.scss │ │ ├── _prefixer.scss │ │ ├── _preloader.scss │ │ ├── _roboto.scss │ │ ├── _sideNav.scss │ │ ├── _slider.scss │ │ ├── _table_of_contents.scss │ │ ├── _tabs.scss │ │ ├── _toast.scss │ │ ├── _tooltip.scss │ │ ├── _typography.scss │ │ ├── _variables.scss │ │ ├── _waves.scss │ │ └── date_picker │ │ │ ├── _default.date.scss │ │ │ ├── _default.scss │ │ │ └── _default.time.scss │ │ ├── materialNote.scss │ │ └── materialize.scss ├── upload │ ├── backup.go │ └── upload.go └── user │ └── auth.go ├── api ├── analytics │ ├── backup.go │ ├── batch.go │ └── init.go ├── cors.go ├── create.go ├── delete.go ├── gzip.go ├── handlers.go ├── hide.go ├── json.go ├── omit.go ├── push.go ├── record.go ├── search.go ├── server.go └── update.go ├── backup └── archive.go ├── cfg └── env.go ├── db ├── addon.go ├── backup.go ├── cache.go ├── config.go ├── content.go ├── index.go ├── init.go ├── upload.go └── user.go ├── item ├── item.go ├── types.go └── upload.go ├── search ├── backup.go └── search.go ├── system.go └── tls ├── devcerts.go ├── enable.go └── enabledev.go /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/golang:1.10 6 | 7 | steps: 8 | - checkout 9 | 10 | # generate and build project to test 11 | - run: curl https://raw.githubusercontent.com/ponzu-cms/ponzu/ponzu-dev/.circleci/test-setup.sh | sh 12 | 13 | # run tests 14 | - run: curl https://raw.githubusercontent.com/ponzu-cms/ponzu/ponzu-dev/.circleci/test-run.sh | sh 15 | 16 | -------------------------------------------------------------------------------- /.circleci/test-run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Test that the configuration runs. 4 | 5 | set -ex 6 | 7 | cd /go/src/github.com/ponzu-cms/ci/test-project 8 | 9 | ponzu run --dev-https & 10 | 11 | # Smoke test 12 | sleep 2 13 | curl -Lk https://localhost:10443/admin | grep https://www.bosssauce.it 14 | 15 | # Run unit tests 16 | touch cookies 17 | 18 | # Create initial admin user 19 | curl -v --cookie-jar cookies \ 20 | -d "name=Test&domain=localhost&email=test@ponzu-cms.org&password=ponzu" \ 21 | -X POST localhost:8080/admin/init 22 | 23 | #Test that content types were generated 24 | curl -b cookies -c cookies http://localhost:8080/admin/contents?type=Person \ 25 | | grep Person 26 | 27 | curl -b cookies -c cookies http://localhost:8080/admin/contents?type=Message \ 28 | | grep Message 29 | 30 | -------------------------------------------------------------------------------- /.circleci/test-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Set up test environment 4 | 5 | set -ex 6 | 7 | # Install Ponzu CMS 8 | go get -u github.com/ponzu-cms/ponzu/... 9 | 10 | # test install 11 | ponzu 12 | 13 | # create a project and generate code 14 | if [ $CIRCLE_BRANCH = "ponzu-dev" ]; then 15 | # ensure we have the latest from ponzu-dev branch 16 | cd /go/src/github.com/ponzu-cms/ponzu 17 | git checkout ponzu-dev 18 | git pull origin ponzu-dev 19 | 20 | # create new project using the ponzu-dev branch 21 | ponzu new --dev github.com/ponzu-cms/ci/test-project 22 | else 23 | ponzu new github.com/ponzu-cms/ci/test-project 24 | fi 25 | 26 | cd /go/src/github.com/ponzu-cms/ci/test-project 27 | 28 | ponzu gen content person name:string hashed_secret:string 29 | ponzu gen content message from:@person,hashed_secret to:@person,hashed_secret 30 | 31 | # build and run dev http/2 server with TLS 32 | ponzu build 33 | 34 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | cmd/ponzu/vendor/* linguist-vendored=false 2 | system/admin/static/dashboard/js/* linguist-vendored 3 | system/admin/static/dashboard/css/* linguist-vendored 4 | system/admin/static/dashboard/fonts/* linguist-vendored 5 | system/admin/static/dashboard/css/admin.css linguist-vendored=false 6 | system/admin/static/editor/js/* linguist-vendored 7 | system/admin/static/editor/sass/* linguist-vendored 8 | system/admin/static/editor/css/* linguist-vendored 9 | system/admin/static/editor/font/* linguist-vendored 10 | system/admin/static/common/js/* linguist-vendored 11 | system/admin/static/common/js/util.js linguist-vendored=false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /ponzu-server 2 | /uploads 3 | /search 4 | /*.db 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | 1. Checkout branch ponzu-dev 4 | 2. Make code changes 5 | 3. Test changes to ponzu-dev branch 6 | - make a commit to ponzu-dev 7 | - to manually test, you will need to use a new copy (ponzu new path/to/code), but pass the --dev flag so that ponzu generates a new copy from the ponzu-dev branch, not master by default (i.e. `$ponzu new --dev /path/to/code`) 8 | - build and run with $ ponzu build and $ ponzu run 9 | 4. To add back to master: 10 | - first push to origin ponzu-dev 11 | - create a pull request 12 | - will then be merged into master 13 | 14 | _A typical contribution workflow might look like:_ 15 | ```bash 16 | # clone the repository and checkout ponzu-dev 17 | $ git clone https://github.com/ponzu-cms/ponzu path/to/local/ponzu # (or your fork) 18 | $ git checkout ponzu-dev 19 | 20 | # install ponzu with go get or from your own local path 21 | $ go get github.com/ponzu-cms/ponzu/... 22 | # or 23 | $ cd /path/to/local/ponzu 24 | $ go install ./... 25 | 26 | # edit files, add features, etc 27 | $ git add -A 28 | $ git commit -m 'edited files, added features, etc' 29 | 30 | # now you need to test the feature.. make a new ponzu project, but pass --dev flag 31 | $ ponzu new --dev /path/to/new/project # will create $GOPATH/src/path/to/new/project 32 | 33 | # build & run ponzu from the new project directory 34 | $ cd /path/to/new/project 35 | $ ponzu build && ponzu run 36 | 37 | # push to your origin:ponzu-dev branch and create a PR at ponzu-cms/ponzu 38 | $ git push origin ponzu-dev 39 | # ... go to https://github.com/ponzu-cms/ponzu and create a PR 40 | ``` 41 | 42 | **Note:** if you intend to work on your own fork and contribute from it, you will 43 | need to also pass `--fork=path/to/your/fork` (using OS-standard filepath structure), 44 | where `path/to/your/fork` _must_ be within `$GOPATH/src`, and you are working from a branch 45 | called `ponzu-dev`. 46 | 47 | For example: 48 | ```bash 49 | # ($GOPATH/src is implied in the fork path, do not add it yourself) 50 | $ ponzu new --dev --fork=github.com/nilslice/ponzu /path/to/new/project 51 | ``` 52 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | 2 | # Base our image on an official, minimal image of our preferred golang 3 | FROM golang:1.9 4 | 5 | # Note: The default golang docker image, already has the GOPATH env variable set. 6 | # GOPATH is located at /go 7 | ENV GO_SRC $GOPATH/src 8 | ENV PONZU_GITHUB github.com/ponzu-cms/ponzu 9 | ENV PONZU_ROOT $GO_SRC/$PONZU_GITHUB 10 | 11 | # Consider updating package in the future. For instance ca-certificates etc. 12 | # RUN apt-get update -qq && apt-get install -y build-essential 13 | 14 | # Make the ponzu root directory 15 | RUN mkdir -p $PONZU_ROOT 16 | 17 | # All commands will be run inside of ponzu root 18 | WORKDIR $PONZU_ROOT 19 | 20 | # Copy the ponzu source into ponzu root. 21 | COPY . . 22 | 23 | # the following runs the code inside of the $GO_SRC/$PONZU_GITHUB directory 24 | RUN go get -u $PONZU_GITHUB... 25 | 26 | # Define the scripts we want run once the container boots 27 | # CMD [ "" ] 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2016 Boss Sauce Creative, LLC. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /addons/README.md: -------------------------------------------------------------------------------- 1 | # Addons 2 | 3 | Place packages inside this directory to extend upon Ponzu core. Find more addons 4 | from the official repository at https://github.com/ponzu-cms/addons 5 | 6 | All packages inside this directory get vendored upon executing `$ ponzu build` 7 | 8 | To submit an official addon, fork the repository at the URL above and make a 9 | pull request including your addon inside a directory without its own git 10 | repository. 11 | 12 | Questions? Reach out to [@ponzu_cms](https://twitter.com/ponzu_cms) on Twitter, 13 | or open an issue at https://github.com/ponzu-cms/ponzu -------------------------------------------------------------------------------- /addons/github.com/bosssauce/reference/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2016 Boss Sauce Creative, LLC. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /addons/github.com/bosssauce/reference/README.md: -------------------------------------------------------------------------------- 1 | # Reference 2 | 3 | A Ponzu addon to embed a reference to a content type from within another content type in the CMS. 4 | -------------------------------------------------------------------------------- /cmd/ponzu/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2016 Boss Sauce Creative, LLC. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /cmd/ponzu/build.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "path/filepath" 5 | "strings" 6 | 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | func buildPonzuServer() error { 11 | // copy all ./content files to internal vendor directory 12 | src := "content" 13 | dst := filepath.Join("cmd", "ponzu", "vendor", "github.com", "ponzu-cms", "ponzu", "content") 14 | err := emptyDir(dst) 15 | if err != nil { 16 | return err 17 | } 18 | err = copyFilesWarnConflicts(src, dst, []string{"doc.go"}) 19 | if err != nil { 20 | return err 21 | } 22 | 23 | // copy all ./addons files & dirs to internal vendor directory 24 | src = "addons" 25 | dst = filepath.Join("cmd", "ponzu", "vendor") 26 | err = copyFilesWarnConflicts(src, dst, nil) 27 | if err != nil { 28 | return err 29 | } 30 | 31 | // execute go build -o ponzu-cms cmd/ponzu/*.go 32 | cmdPackageName := strings.Join([]string{".", "cmd", "ponzu"}, "/") 33 | buildOptions := []string{"build", "-o", buildOutputName(), cmdPackageName} 34 | return execAndWait(gocmd, buildOptions...) 35 | } 36 | 37 | var buildCmd = &cobra.Command{ 38 | Use: "build [flags]", 39 | Short: "build will build/compile the project to then be run.", 40 | Long: `From within your Ponzu project directory, running build will copy and move 41 | the necessary files from your workspace into the vendored directory, and 42 | will build/compile the project to then be run. 43 | 44 | By providing the 'gocmd' flag, you can specify which Go command to build the 45 | project, if testing a different release of Go. 46 | 47 | Errors will be reported, but successful build commands return nothing.`, 48 | Example: `$ ponzu build 49 | (or) 50 | $ ponzu build --gocmd=go1.8rc1`, 51 | RunE: func(cmd *cobra.Command, args []string) error { 52 | return buildPonzuServer() 53 | }, 54 | } 55 | 56 | func init() { 57 | RegisterCmdlineCommand(buildCmd) 58 | } 59 | -------------------------------------------------------------------------------- /cmd/ponzu/cli_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func TestParseType(t *testing.T) { 6 | // blog title:string Author:string PostCategory:string content:string some_thing:int 7 | args := []string{ 8 | "blog", "title:string", "Author:string", 9 | "PostCategory:string", "content:string", 10 | "some_thing:int", "Some_otherThing:float64", 11 | } 12 | 13 | gt, err := parseType(args) 14 | if err != nil { 15 | t.Errorf("Failed: %s", err.Error()) 16 | } 17 | 18 | if gt.Name != "Blog" { 19 | t.Errorf("Expected %s, got: %s", "Blog", gt.Name) 20 | } 21 | } 22 | 23 | func TestFieldJSONName(t *testing.T) { 24 | cases := map[string]string{ 25 | "_T": "t", 26 | "T": "t", 27 | "_tT_": "t_t_", 28 | "TestCapsNoSym": "test_caps_no_sym", 29 | "test_Some_caps_Sym": "test_some_caps_sym", 30 | "testnocaps": "testnocaps", 31 | "_Test_Caps_Sym_odd": "test_caps_sym_odd", 32 | "test-hyphen": "test-hyphen", 33 | "Test-hyphen-Caps": "test-hyphen-caps", 34 | "Test-Hyphen_Sym-Caps": "test-hyphen_sym-caps", 35 | } 36 | 37 | for input, expected := range cases { 38 | output := fieldJSONName(input) 39 | if output != expected { 40 | t.Errorf("Expected: %s, got: %s", expected, output) 41 | } 42 | } 43 | } 44 | 45 | func TestFieldName(t *testing.T) { 46 | cases := map[string]string{ 47 | "_T": "T", 48 | "T": "T", 49 | "_tT_": "TT", 50 | "TestCapsNoSym": "TestCapsNoSym", 51 | "test_Some_caps_Sym": "TestSomeCapsSym", 52 | "testnocaps": "Testnocaps", 53 | "_Test_Caps_Sym_odd": "TestCapsSymOdd", 54 | "test-hyphen": "TestHyphen", 55 | "Test-hyphen-Caps": "TestHyphenCaps", 56 | "Test-Hyphen_Sym-Caps": "TestHyphenSymCaps", 57 | } 58 | 59 | for input, expected := range cases { 60 | output := fieldName(input) 61 | if output != expected { 62 | t.Errorf("Expected: %s, got: %s", expected, output) 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /cmd/ponzu/new_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "testing" 7 | ) 8 | 9 | func TestNewName2Path(t *testing.T) { 10 | savedGOPATH := os.Getenv("GOPATH") 11 | defer os.Setenv("GOPATH", savedGOPATH) 12 | pwd, err := os.Getwd() 13 | if err != nil { 14 | t.Fatalf("Could not determine current working directory: %s", err) 15 | } 16 | 17 | isNil := func(e error) bool { return e == nil } 18 | isNonNil := func(e error) bool { return e != nil } 19 | 20 | baseDir := filepath.Join(pwd, "test-fixtures", "new") 21 | 22 | testTable := []struct { 23 | gopath, wd, a, 24 | wantP string 25 | wantE func(e error) bool 26 | }{{ 27 | gopath: baseDir, 28 | wd: filepath.Join("src", "existing"), 29 | a: ".", 30 | wantP: filepath.Join(pwd, "test-fixtures", "new", "src", "existing"), 31 | wantE: os.IsExist, 32 | }, { 33 | gopath: baseDir, 34 | wd: filepath.Join(""), 35 | a: "non-existing", 36 | wantP: filepath.Join(pwd, "test-fixtures", "new", "src", "non-existing"), 37 | wantE: isNil, 38 | }, { 39 | gopath: baseDir, 40 | wd: filepath.Join(""), 41 | a: ".", 42 | wantP: "", 43 | wantE: isNonNil, 44 | }, { 45 | gopath: baseDir, 46 | wd: "..", 47 | a: ".", 48 | wantP: "", 49 | wantE: isNonNil, 50 | }} 51 | 52 | for _, test := range testTable { 53 | os.Setenv("GOPATH", test.gopath) 54 | err = os.Chdir(filepath.Join(test.gopath, test.wd)) 55 | if err != nil { 56 | t.Fatalf("could not setup base: %s", err) 57 | } 58 | got, gotE := name2path(test.a) 59 | if got != test.wantP { 60 | t.Errorf("got '%s', want: '%s'", got, test.wantP) 61 | } 62 | if !test.wantE(gotE) { 63 | t.Errorf("got error '%s'", gotE) 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /cmd/ponzu/paths.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "os/user" 6 | "path/filepath" 7 | "runtime" 8 | "strings" 9 | ) 10 | 11 | // buildOutputName returns the correct ponzu-server file name 12 | // based on the host Operating System 13 | func buildOutputName() string { 14 | if runtime.GOOS == "windows" { 15 | return "ponzu-server.exe" 16 | } 17 | 18 | return "ponzu-server" 19 | } 20 | 21 | // resolve GOPATH. In 1.8 can be default, or custom. A custom GOPATH can 22 | // also contain multiple paths, in which case 'go get' uses the first 23 | func getGOPATH() (string, error) { 24 | var gopath string 25 | gopath = os.Getenv("GOPATH") 26 | if gopath == "" { 27 | // not set, find the default 28 | usr, err := user.Current() 29 | if err != nil { 30 | return gopath, err 31 | } 32 | gopath = filepath.Join(usr.HomeDir, "go") 33 | } else { 34 | // parse out in case of multiple, retain first 35 | if runtime.GOOS == "windows" { 36 | gopaths := strings.Split(gopath, ";") 37 | gopath = gopaths[0] 38 | } else { 39 | gopaths := strings.Split(gopath, ":") 40 | gopath = gopaths[0] 41 | } 42 | } 43 | return gopath, nil 44 | } 45 | -------------------------------------------------------------------------------- /cmd/ponzu/ponzu.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.11.0" 3 | } 4 | -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-checkbox.tmpl: -------------------------------------------------------------------------------- 1 | View: editor.Checkbox("{{ .Name }}", {{ .Initial }}, map[string]string{ 2 | "label": "{{ .Name }}", 3 | }, map[string]string{ 4 | // "value": "Display Name", 5 | }), -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-content.tmpl: -------------------------------------------------------------------------------- 1 | package content 2 | 3 | import ( 4 | "fmt" 5 | {{ if .HasReferences }} 6 | "github.com/bosssauce/reference" 7 | {{ end }} 8 | "github.com/ponzu-cms/ponzu/management/editor" 9 | "github.com/ponzu-cms/ponzu/system/item" 10 | ) 11 | 12 | type {{ .Name }} struct { 13 | item.Item 14 | 15 | {{ range .Fields }}{{ .Name }} {{ .TypeName }} `json:"{{ .JSONName }}"` 16 | {{ end }} 17 | } 18 | 19 | // MarshalEditor writes a buffer of html to edit a {{ .Name }} within the CMS 20 | // and implements editor.Editable 21 | func ({{ .Initial }} *{{ .Name }}) MarshalEditor() ([]byte, error) { 22 | view, err := editor.Form({{ .Initial }}, 23 | // Take note that the first argument to these Input-like functions 24 | // is the string version of each {{ .Name }} field, and must follow 25 | // this pattern for auto-decoding and auto-encoding reasons: 26 | {{ range .Fields }}editor.Field{ 27 | {{ .View }} 28 | }, 29 | {{ end }} 30 | ) 31 | 32 | if err != nil { 33 | return nil, fmt.Errorf("Failed to render {{ .Name }} editor view: %s", err.Error()) 34 | } 35 | 36 | return view, nil 37 | } 38 | 39 | func init() { 40 | item.Types["{{ .Name }}"] = func() interface{} { return new({{ .Name }}) } 41 | } 42 | 43 | // String defines how a {{ .Name }} is printed. Update it using more descriptive 44 | // fields from the {{ .Name }} struct type 45 | func ({{ .Initial }} *{{ .Name }}) String() string { 46 | return fmt.Sprintf("{{ .Name }}: %s", {{ .Initial }}.UUID) 47 | } -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-custom.tmpl: -------------------------------------------------------------------------------- 1 | View: []byte(` 2 |
3 | 4 | 5 |
6 | `), -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-file-repeater.tmpl: -------------------------------------------------------------------------------- 1 | View: editor.FileRepeater("{{ .Name }}", {{ .Initial }}, map[string]string{ 2 | "label": "{{ .Name }}", 3 | "placeholder": "Upload the {{ .Name }} here", 4 | }), -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-file.tmpl: -------------------------------------------------------------------------------- 1 | View: editor.File("{{ .Name }}", {{ .Initial }}, map[string]string{ 2 | "label": "{{ .Name }}", 3 | "placeholder": "Upload the {{ .Name }} here", 4 | }), -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-hidden.tmpl: -------------------------------------------------------------------------------- 1 | View: editor.Input("{{ .Name }}", {{ .Initial }}, map[string]string{ 2 | "type": "hidden", 3 | }), -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-input-repeater.tmpl: -------------------------------------------------------------------------------- 1 | View: editor.InputRepeater("{{ .Name }}", {{ .Initial }}, map[string]string{ 2 | "label": "{{ .Name }}", 3 | "type": "text", 4 | "placeholder": "Enter the {{ .Name }} here", 5 | }), -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-input.tmpl: -------------------------------------------------------------------------------- 1 | View: editor.Input("{{ .Name }}", {{ .Initial }}, map[string]string{ 2 | "label": "{{ .Name }}", 3 | "type": "text", 4 | "placeholder": "Enter the {{ .Name }} here", 5 | }), -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-reference-repeater.tmpl: -------------------------------------------------------------------------------- 1 | View: reference.SelectRepeater("[[ .Name ]]", [[ .Initial ]], map[string]string{ 2 | "label": "[[ .Name ]]", 3 | }, 4 | "[[ .ReferenceName ]]", 5 | `[[ range .ReferenceJSONTags ]]{{ .[[ . ]] }} [[ else ]][[ .ReferenceName ]]: {{ .id }}[[ end ]]`, 6 | ), 7 | -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-reference.tmpl: -------------------------------------------------------------------------------- 1 | View: reference.Select("[[ .Name ]]", [[ .Initial ]], map[string]string{ 2 | "label": "[[ .Name ]]", 3 | }, 4 | "[[ .ReferenceName ]]", 5 | `[[ range .ReferenceJSONTags ]]{{ .[[ . ]] }} [[ else ]][[ .ReferenceName ]]: {{ .id }}[[ end ]]`, 6 | ), 7 | -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-richtext.tmpl: -------------------------------------------------------------------------------- 1 | View: editor.Richtext("{{ .Name }}", {{ .Initial }}, map[string]string{ 2 | "label": "{{ .Name }}", 3 | "placeholder": "Enter the {{ .Name }} here", 4 | }), -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-select-repeater.tmpl: -------------------------------------------------------------------------------- 1 | View: editor.SelectRepeater("{{ .Name }}", {{ .Initial }}, map[string]string{ 2 | "label": "{{ .Name }}", 3 | }, map[string]string{ 4 | // "value": "Display Name", 5 | }), -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-select.tmpl: -------------------------------------------------------------------------------- 1 | View: editor.Select("{{ .Name }}", {{ .Initial }}, map[string]string{ 2 | "label": "{{ .Name }}", 3 | }, map[string]string{ 4 | // "value": "Display Name", 5 | }), -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-tags.tmpl: -------------------------------------------------------------------------------- 1 | View: editor.Tags("{{ .Name }}", {{ .Initial }}, map[string]string{ 2 | "label": "{{ .Name }}", 3 | "placeholder": "+{{ .Name }}", 4 | }), -------------------------------------------------------------------------------- /cmd/ponzu/templates/gen-textarea.tmpl: -------------------------------------------------------------------------------- 1 | View: editor.Textarea("{{ .Name }}", {{ .Initial }}, map[string]string{ 2 | "label": "{{ .Name }}", 3 | "placeholder": "Enter the {{ .Name }} here", 4 | }), -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/.gitignore: -------------------------------------------------------------------------------- 1 | *.prof 2 | *.test 3 | *.swp 4 | /bin/ 5 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Ben Johnson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/Makefile: -------------------------------------------------------------------------------- 1 | BRANCH=`git rev-parse --abbrev-ref HEAD` 2 | COMMIT=`git rev-parse --short HEAD` 3 | GOLDFLAGS="-X main.branch $(BRANCH) -X main.commit $(COMMIT)" 4 | 5 | default: build 6 | 7 | race: 8 | @go test -v -race -test.run="TestSimulate_(100op|1000op)" 9 | 10 | # go get github.com/kisielk/errcheck 11 | errcheck: 12 | @errcheck -ignorepkg=bytes -ignore=os:Remove github.com/boltdb/bolt 13 | 14 | test: 15 | @go test -v -cover . 16 | @go test -v ./cmd/bolt 17 | 18 | .PHONY: fmt test 19 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | os: Windows Server 2012 R2 4 | 5 | clone_folder: c:\gopath\src\github.com\boltdb\bolt 6 | 7 | environment: 8 | GOPATH: c:\gopath 9 | 10 | install: 11 | - echo %PATH% 12 | - echo %GOPATH% 13 | - go version 14 | - go env 15 | - go get -v -t ./... 16 | 17 | build_script: 18 | - go test -v ./... 19 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_386.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | // maxMapSize represents the largest mmap size supported by Bolt. 4 | const maxMapSize = 0x7FFFFFFF // 2GB 5 | 6 | // maxAllocSize is the size used when creating array pointers. 7 | const maxAllocSize = 0xFFFFFFF 8 | 9 | // Are unaligned load/stores broken on this arch? 10 | var brokenUnaligned = false 11 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_amd64.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | // maxMapSize represents the largest mmap size supported by Bolt. 4 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 5 | 6 | // maxAllocSize is the size used when creating array pointers. 7 | const maxAllocSize = 0x7FFFFFFF 8 | 9 | // Are unaligned load/stores broken on this arch? 10 | var brokenUnaligned = false 11 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_arm.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import "unsafe" 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0x7FFFFFFF // 2GB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0xFFFFFFF 10 | 11 | // Are unaligned load/stores broken on this arch? 12 | var brokenUnaligned bool 13 | 14 | func init() { 15 | // Simple check to see whether this arch handles unaligned load/stores 16 | // correctly. 17 | 18 | // ARM9 and older devices require load/stores to be from/to aligned 19 | // addresses. If not, the lower 2 bits are cleared and that address is 20 | // read in a jumbled up order. 21 | 22 | // See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15414.html 23 | 24 | raw := [6]byte{0xfe, 0xef, 0x11, 0x22, 0x22, 0x11} 25 | val := *(*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&raw)) + 2)) 26 | 27 | brokenUnaligned = val != 0x11222211 28 | } 29 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_arm64.go: -------------------------------------------------------------------------------- 1 | // +build arm64 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | 11 | // Are unaligned load/stores broken on this arch? 12 | var brokenUnaligned = false 13 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_linux.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | // fdatasync flushes written data to a file descriptor. 8 | func fdatasync(db *DB) error { 9 | return syscall.Fdatasync(int(db.file.Fd())) 10 | } 11 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_openbsd.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | const ( 9 | msAsync = 1 << iota // perform asynchronous writes 10 | msSync // perform synchronous writes 11 | msInvalidate // invalidate cached data 12 | ) 13 | 14 | func msync(db *DB) error { 15 | _, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(db.data)), uintptr(db.datasz), msInvalidate) 16 | if errno != 0 { 17 | return errno 18 | } 19 | return nil 20 | } 21 | 22 | func fdatasync(db *DB) error { 23 | if db.data != nil { 24 | return msync(db) 25 | } 26 | return db.file.Sync() 27 | } 28 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc.go: -------------------------------------------------------------------------------- 1 | // +build ppc 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0x7FFFFFFF // 2GB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0xFFFFFFF 10 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc64.go: -------------------------------------------------------------------------------- 1 | // +build ppc64 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc64le.go: -------------------------------------------------------------------------------- 1 | // +build ppc64le 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | 11 | // Are unaligned load/stores broken on this arch? 12 | var brokenUnaligned = false 13 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_s390x.go: -------------------------------------------------------------------------------- 1 | // +build s390x 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | 11 | // Are unaligned load/stores broken on this arch? 12 | var brokenUnaligned = false 13 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_unix_solaris.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "syscall" 7 | "time" 8 | "unsafe" 9 | 10 | "golang.org/x/sys/unix" 11 | ) 12 | 13 | // flock acquires an advisory lock on a file descriptor. 14 | func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { 15 | var t time.Time 16 | for { 17 | // If we're beyond our timeout then return an error. 18 | // This can only occur after we've attempted a flock once. 19 | if t.IsZero() { 20 | t = time.Now() 21 | } else if timeout > 0 && time.Since(t) > timeout { 22 | return ErrTimeout 23 | } 24 | var lock syscall.Flock_t 25 | lock.Start = 0 26 | lock.Len = 0 27 | lock.Pid = 0 28 | lock.Whence = 0 29 | lock.Pid = 0 30 | if exclusive { 31 | lock.Type = syscall.F_WRLCK 32 | } else { 33 | lock.Type = syscall.F_RDLCK 34 | } 35 | err := syscall.FcntlFlock(db.file.Fd(), syscall.F_SETLK, &lock) 36 | if err == nil { 37 | return nil 38 | } else if err != syscall.EAGAIN { 39 | return err 40 | } 41 | 42 | // Wait for a bit and try again. 43 | time.Sleep(50 * time.Millisecond) 44 | } 45 | } 46 | 47 | // funlock releases an advisory lock on a file descriptor. 48 | func funlock(db *DB) error { 49 | var lock syscall.Flock_t 50 | lock.Start = 0 51 | lock.Len = 0 52 | lock.Type = syscall.F_UNLCK 53 | lock.Whence = 0 54 | return syscall.FcntlFlock(uintptr(db.file.Fd()), syscall.F_SETLK, &lock) 55 | } 56 | 57 | // mmap memory maps a DB's data file. 58 | func mmap(db *DB, sz int) error { 59 | // Map the data file to memory. 60 | b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | // Advise the kernel that the mmap is accessed randomly. 66 | if err := unix.Madvise(b, syscall.MADV_RANDOM); err != nil { 67 | return fmt.Errorf("madvise: %s", err) 68 | } 69 | 70 | // Save the original byte slice and convert to a byte array pointer. 71 | db.dataref = b 72 | db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0])) 73 | db.datasz = sz 74 | return nil 75 | } 76 | 77 | // munmap unmaps a DB's data file from memory. 78 | func munmap(db *DB) error { 79 | // Ignore the unmap if we have no mapped data. 80 | if db.dataref == nil { 81 | return nil 82 | } 83 | 84 | // Unmap using the original byte slice. 85 | err := unix.Munmap(db.dataref) 86 | db.dataref = nil 87 | db.data = nil 88 | db.datasz = 0 89 | return err 90 | } 91 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/boltsync_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!plan9,!linux,!openbsd 2 | 3 | package bolt 4 | 5 | // fdatasync flushes written data to a file descriptor. 6 | func fdatasync(db *DB) error { 7 | return db.file.Sync() 8 | } 9 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package bolt implements a low-level key/value store in pure Go. It supports 3 | fully serializable transactions, ACID semantics, and lock-free MVCC with 4 | multiple readers and a single writer. Bolt can be used for projects that 5 | want a simple data store without the need to add large dependencies such as 6 | Postgres or MySQL. 7 | 8 | Bolt is a single-level, zero-copy, B+tree data store. This means that Bolt is 9 | optimized for fast read access and does not require recovery in the event of a 10 | system crash. Transactions which have not finished committing will simply be 11 | rolled back in the event of a crash. 12 | 13 | The design of Bolt is based on Howard Chu's LMDB database project. 14 | 15 | Bolt currently works on Windows, Mac OS X, and Linux. 16 | 17 | 18 | Basics 19 | 20 | There are only a few types in Bolt: DB, Bucket, Tx, and Cursor. The DB is 21 | a collection of buckets and is represented by a single file on disk. A bucket is 22 | a collection of unique keys that are associated with values. 23 | 24 | Transactions provide either read-only or read-write access to the database. 25 | Read-only transactions can retrieve key/value pairs and can use Cursors to 26 | iterate over the dataset sequentially. Read-write transactions can create and 27 | delete buckets and can insert and remove keys. Only one read-write transaction 28 | is allowed at a time. 29 | 30 | 31 | Caveats 32 | 33 | The database uses a read-only, memory-mapped data file to ensure that 34 | applications cannot corrupt the database, however, this means that keys and 35 | values returned from Bolt cannot be changed. Writing to a read-only byte slice 36 | will cause Go to panic. 37 | 38 | Keys and values retrieved from the database are only valid for the life of 39 | the transaction. When used outside the transaction, these byte slices can 40 | point to different data or can point to invalid memory which will cause a panic. 41 | 42 | 43 | */ 44 | package bolt 45 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/boltdb/bolt/page_test.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "reflect" 5 | "sort" 6 | "testing" 7 | "testing/quick" 8 | ) 9 | 10 | // Ensure that the page type can be returned in human readable format. 11 | func TestPage_typ(t *testing.T) { 12 | if typ := (&page{flags: branchPageFlag}).typ(); typ != "branch" { 13 | t.Fatalf("exp=branch; got=%v", typ) 14 | } 15 | if typ := (&page{flags: leafPageFlag}).typ(); typ != "leaf" { 16 | t.Fatalf("exp=leaf; got=%v", typ) 17 | } 18 | if typ := (&page{flags: metaPageFlag}).typ(); typ != "meta" { 19 | t.Fatalf("exp=meta; got=%v", typ) 20 | } 21 | if typ := (&page{flags: freelistPageFlag}).typ(); typ != "freelist" { 22 | t.Fatalf("exp=freelist; got=%v", typ) 23 | } 24 | if typ := (&page{flags: 20000}).typ(); typ != "unknown<4e20>" { 25 | t.Fatalf("exp=unknown<4e20>; got=%v", typ) 26 | } 27 | } 28 | 29 | // Ensure that the hexdump debugging function doesn't blow up. 30 | func TestPage_dump(t *testing.T) { 31 | (&page{id: 256}).hexdump(16) 32 | } 33 | 34 | func TestPgids_merge(t *testing.T) { 35 | a := pgids{4, 5, 6, 10, 11, 12, 13, 27} 36 | b := pgids{1, 3, 8, 9, 25, 30} 37 | c := a.merge(b) 38 | if !reflect.DeepEqual(c, pgids{1, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 25, 27, 30}) { 39 | t.Errorf("mismatch: %v", c) 40 | } 41 | 42 | a = pgids{4, 5, 6, 10, 11, 12, 13, 27, 35, 36} 43 | b = pgids{8, 9, 25, 30} 44 | c = a.merge(b) 45 | if !reflect.DeepEqual(c, pgids{4, 5, 6, 8, 9, 10, 11, 12, 13, 25, 27, 30, 35, 36}) { 46 | t.Errorf("mismatch: %v", c) 47 | } 48 | } 49 | 50 | func TestPgids_merge_quick(t *testing.T) { 51 | if err := quick.Check(func(a, b pgids) bool { 52 | // Sort incoming lists. 53 | sort.Sort(a) 54 | sort.Sort(b) 55 | 56 | // Merge the two lists together. 57 | got := a.merge(b) 58 | 59 | // The expected value should be the two lists combined and sorted. 60 | exp := append(a, b...) 61 | sort.Sort(exp) 62 | 63 | if !reflect.DeepEqual(exp, got) { 64 | t.Errorf("\nexp=%+v\ngot=%+v\n", exp, got) 65 | return false 66 | } 67 | 68 | return true 69 | }, nil); err != nil { 70 | t.Fatal(err) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # binary bundle generated by go-fuzz 15 | uuid-fuzz.zip 16 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | go: 4 | - 1.7 5 | - 1.8 6 | - 1.9 7 | - "1.10" 8 | - tip 9 | matrix: 10 | allow_failures: 11 | - go: tip 12 | fast_finish: true 13 | before_install: 14 | - go get github.com/mattn/goveralls 15 | - go get golang.org/x/tools/cmd/cover 16 | script: 17 | - $HOME/gopath/bin/goveralls -service=travis-ci 18 | notifications: 19 | email: false 20 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013-2018 by Maxim Bublis 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/fuzz.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Andrei Tudor Călin 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining 4 | // a copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to 8 | // permit persons to whom the Software is furnished to do so, subject to 9 | // the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be 12 | // included in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // +build gofuzz 23 | 24 | package uuid 25 | 26 | // Fuzz implements a simple fuzz test for FromString / UnmarshalText. 27 | // 28 | // To run: 29 | // 30 | // $ go get github.com/dvyukov/go-fuzz/... 31 | // $ cd $GOPATH/src/github.com/gofrs/uuid 32 | // $ go-fuzz-build github.com/gofrs/uuid 33 | // $ go-fuzz -bin=uuid-fuzz.zip -workdir=./testdata 34 | // 35 | // If you make significant changes to FromString / UnmarshalText and add 36 | // new cases to fromStringTests (in codec_test.go), please run 37 | // 38 | // $ go test -seed_fuzz_corpus 39 | // 40 | // to seed the corpus with the new interesting inputs, then run the fuzzer. 41 | func Fuzz(data []byte) int { 42 | _, err := FromString(string(data)) 43 | if err != nil { 44 | return 0 45 | } 46 | return 1 47 | } 48 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/1416586f4a34d02bcb506f6107b40df512b9f2f9: -------------------------------------------------------------------------------- 1 | zba7b810-9dad-11d1-80b4-00c04fd4 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/3b46a7e7b02ec193581e6c9fa2c8a72f50a64e08-1: -------------------------------------------------------------------------------- 1 | 6ba7b810-9dad-11d1-80F4-00c"4fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/50c54bb75fcfdc488f162bf2f0c6dec6103bfa18-5: -------------------------------------------------------------------------------- 1 | 6ad1DdE8dda91DdE80F400c0Bool30t: -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/69c581ab749cbd56be8684d3a58ac2cfab9af0f4-5: -------------------------------------------------------------------------------- 1 | 6ba7b810Edad1DdE80F400c0Bool30c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/752bf000e0bff06777dd0d6f0be6353844de678a-3: -------------------------------------------------------------------------------- 1 | 6ba7b8109dad1Dd180F400c0Bool30c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/a4483762d4ece8466d82cca5cacd35a0829c4e60-2: -------------------------------------------------------------------------------- 1 | 6ba7b810-9dad-11d1-80F4-F0c"4fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/d0952c45e0c823fc5cc12bcf7d9b877d150ab523-1: -------------------------------------------------------------------------------- 1 | 6ba7b8109dad11d180b400c0Bool30c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/e2b84d2065846891f18ae109b12e01d224e1c7c3-4: -------------------------------------------------------------------------------- 1 | 6ba7b8109dad1DdE80F400c0Bool30c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/e320d749435115e874f77420e17d0937e07f69f3-2: -------------------------------------------------------------------------------- 1 | 6ba7b8109dad1Dd180b400c0Bool30c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/ed132d47d757f6468443a22df8a2a965efb34098-7: -------------------------------------------------------------------------------- 1 | 6ba1DdE8dDAE8DdE80F400c0BoUl30to -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/eeefb01f7bb3c627aedb292c994b20f739ffd613-6: -------------------------------------------------------------------------------- 1 | 6ad1DdE8dDdE8DdE80F400c0Bool30t: -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_0: -------------------------------------------------------------------------------- 1 | 6ba7b810-9dad-11d1-80b4-00c04fd430c -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_1: -------------------------------------------------------------------------------- 1 | 6ba7b8109dad11d180b400c04fd430c -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_10: -------------------------------------------------------------------------------- 1 | uuid:urn:6ba7b810-9dad-11d1-80b4-00c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_11: -------------------------------------------------------------------------------- 1 | uuid:urn:6ba7b8109dad11d180b400c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_12: -------------------------------------------------------------------------------- 1 | 6ba7b8109-dad-11d1-80b4-00c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_13: -------------------------------------------------------------------------------- 1 | 6ba7b810-9dad1-1d1-80b4-00c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_14: -------------------------------------------------------------------------------- 1 | 6ba7b810-9dad-11d18-0b4-00c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_15: -------------------------------------------------------------------------------- 1 | 6ba7b810-9dad-11d1-80b40-0c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_16: -------------------------------------------------------------------------------- 1 | 6ba7b810+9dad+11d1+80b4+00c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_17: -------------------------------------------------------------------------------- 1 | (6ba7b810-9dad-11d1-80b4-00c04fd430c8} -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_18: -------------------------------------------------------------------------------- 1 | {6ba7b810-9dad-11d1-80b4-00c04fd430c8> -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_19: -------------------------------------------------------------------------------- 1 | zba7b810-9dad-11d1-80b4-00c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_2: -------------------------------------------------------------------------------- 1 | 6ba7b8109dad11d180b400c04fd430q8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_20: -------------------------------------------------------------------------------- 1 | 6ba7b810-9dad11d180b400c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_21: -------------------------------------------------------------------------------- 1 | 6ba7b8109dad-11d180b400c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_22: -------------------------------------------------------------------------------- 1 | 6ba7b8109dad11d1-80b400c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_23: -------------------------------------------------------------------------------- 1 | 6ba7b8109dad11d180b4-00c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_3: -------------------------------------------------------------------------------- 1 | 6ba7b810-9dad-11d1-80b4-00c04fd430c8= -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_4: -------------------------------------------------------------------------------- 1 | 6ba7b810-9dad-11d1-80b4-00c04fd430c8} -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_5: -------------------------------------------------------------------------------- 1 | {6ba7b810-9dad-11d1-80b4-00c04fd430c8}f -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_6: -------------------------------------------------------------------------------- 1 | 6ba7b810-9dad-11d1-80b4-00c04fd430c800c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_7: -------------------------------------------------------------------------------- 1 | ba7b8109dad11d180b400c04fd430c8} -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_8: -------------------------------------------------------------------------------- 1 | 6ba7b8109dad11d180b400c04fd430c86ba7b8109dad11d180b400c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_invalid_9: -------------------------------------------------------------------------------- 1 | urn:uuid:{6ba7b810-9dad-11d1-80b4-00c04fd430c8} -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_valid_BracedCanonical: -------------------------------------------------------------------------------- 1 | {6ba7b810-9dad-11d1-80b4-00c04fd430c8} -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_valid_BracedHashlike: -------------------------------------------------------------------------------- 1 | {6ba7b8109dad11d180b400c04fd430c8} -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_valid_Canonical: -------------------------------------------------------------------------------- 1 | 6ba7b810-9dad-11d1-80b4-00c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_valid_Hashlike: -------------------------------------------------------------------------------- 1 | 6ba7b8109dad11d180b400c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_valid_URNCanonical: -------------------------------------------------------------------------------- 1 | urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gofrs/uuid/testdata/corpus/seed_valid_URNHashlike: -------------------------------------------------------------------------------- 1 | urn:uuid:6ba7b8109dad11d180b400c04fd430c8 -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gorilla/schema/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.3 7 | - go: 1.4 8 | - go: 1.5 9 | - go: 1.6 10 | - go: 1.7 11 | - go: tip 12 | allow_failures: 13 | - go: tip 14 | 15 | script: 16 | - go get -t -v ./... 17 | - diff -u <(echo -n) <(gofmt -d .) 18 | - go vet $(go list ./... | grep -v /vendor/) 19 | - go test -v -race ./... 20 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gorilla/schema/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rodrigo Moraes. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/gorilla/schema/README.md: -------------------------------------------------------------------------------- 1 | schema 2 | ====== 3 | [![GoDoc](https://godoc.org/github.com/gorilla/schema?status.svg)](https://godoc.org/github.com/gorilla/schema) [![Build Status](https://travis-ci.org/gorilla/schema.png?branch=master)](https://travis-ci.org/gorilla/schema) 4 | 5 | Package gorilla/schema fills a struct with form values. 6 | 7 | ## Example 8 | 9 | Here's a quick example: we parse POST form values and then decode them into a struct: 10 | 11 | ```go 12 | // Set a Decoder instance as a package global, because it caches 13 | // meta-data about structs, and an instance can be shared safely. 14 | var decoder = schema.NewDecoder() 15 | 16 | type Person struct { 17 | Name string 18 | Phone string 19 | } 20 | 21 | func MyHandler(w http.ResponseWriter, r *http.Request) { 22 | err := r.ParseForm() 23 | if err != nil { 24 | // Handle error 25 | } 26 | 27 | var person Person 28 | 29 | // r.PostForm is a map of our POST form values 30 | err := decoder.Decode(&person, r.PostForm) 31 | if err != nil { 32 | // Handle error 33 | } 34 | 35 | // Do something with person.Name or person.Phone 36 | } 37 | ``` 38 | 39 | To define custom names for fields, use a struct tag "schema". To not populate certain fields, use a dash for the name and it will be ignored: 40 | 41 | ```go 42 | type Person struct { 43 | Name string `schema:"name"` // custom name 44 | Phone string `schema:"phone"` // custom name 45 | Admin bool `schema:"-"` // this field is never set 46 | } 47 | ``` 48 | 49 | The supported field types in the destination struct are: 50 | 51 | * bool 52 | * float variants (float32, float64) 53 | * int variants (int, int8, int16, int32, int64) 54 | * string 55 | * uint variants (uint, uint8, uint16, uint32, uint64) 56 | * struct 57 | * a pointer to one of the above types 58 | * a slice or a pointer to a slice of one of the above types 59 | 60 | Unsupported types are simply ignored, however custom types can be registered to be converted. 61 | 62 | More examples are available on the Gorilla website: http://www.gorillatoolkit.org/pkg/schema 63 | 64 | ## License 65 | 66 | BSD licensed. See the LICENSE file for details. 67 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/nilslice/email/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Steve Manuel 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 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/nilslice/email/README.md: -------------------------------------------------------------------------------- 1 | ## Email 2 | 3 | I needed a way to send email from a [Ponzu](https://ponzu-cms.org) installation 4 | running on all kinds of systems without shelling out. `sendmail` or `postfix` et 5 | al are not standard on all systems, and I didn't want to force users to add API 6 | keys from a third-party just to send something like an account recovery email. 7 | 8 | ### Usage: 9 | `$ go get github.com/nilslice/email` 10 | 11 | ```go 12 | package main 13 | 14 | import ( 15 | "fmt" 16 | "github.com/nilslice/email" 17 | ) 18 | 19 | func main() { 20 | msg := email.Message{ 21 | To: "you@server.name", // do not add < > or name in quotes 22 | From: "me@server.name", // do not add < > or name in quotes 23 | Subject: "A simple email", 24 | Body: "Plain text email body. HTML not yet supported, but send a PR!", 25 | } 26 | 27 | err := msg.Send() 28 | if err != nil { 29 | fmt.Println(err) 30 | } 31 | } 32 | 33 | ``` 34 | 35 | ### Under the hood 36 | `email` looks at a `Message`'s `To` field, splits the string on the @ symbol and 37 | issues an MX lookup to find the mail exchange server(s). Then it iterates over 38 | all the possibilities in combination with commonly used SMTP ports for non-SSL 39 | clients: `25, 2525, & 587` 40 | 41 | It stops once it has an active client connected to a mail server and sends the 42 | initial information, the message, and then closes the connection. 43 | 44 | Currently, this doesn't support any additional headers or `To` field formatting 45 | (the recipient's email must be the only string `To` takes). Although these would 46 | be fairly strightforward to implement, I don't need them yet.. so feel free to 47 | contribute anything you find useful. 48 | 49 | #### Warning 50 | Be cautious of how often you run this locally or in testing, as it's quite 51 | likely your IP will be blocked/blacklisted if it is not already. -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/nilslice/email/email.go: -------------------------------------------------------------------------------- 1 | package email 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "net/smtp" 7 | "strings" 8 | ) 9 | 10 | // Message creates a email to be sent 11 | type Message struct { 12 | To string 13 | From string 14 | Subject string 15 | Body string 16 | } 17 | 18 | var ( 19 | ports = []int{25, 2525, 587} 20 | ) 21 | 22 | // Send sends a message to recipient(s) listed in the 'To' field of a Message 23 | func (m Message) Send() error { 24 | if !strings.Contains(m.To, "@") { 25 | return fmt.Errorf("Invalid recipient address: <%s>", m.To) 26 | } 27 | 28 | host := strings.Split(m.To, "@")[1] 29 | addrs, err := net.LookupMX(host) 30 | if err != nil { 31 | return err 32 | } 33 | 34 | c, err := newClient(addrs, ports) 35 | if err != nil { 36 | return err 37 | } 38 | 39 | err = send(m, c) 40 | if err != nil { 41 | return err 42 | } 43 | 44 | return nil 45 | } 46 | 47 | func newClient(mx []*net.MX, ports []int) (*smtp.Client, error) { 48 | for i := range mx { 49 | for j := range ports { 50 | server := strings.TrimSuffix(mx[i].Host, ".") 51 | hostPort := fmt.Sprintf("%s:%d", server, ports[j]) 52 | client, err := smtp.Dial(hostPort) 53 | if err != nil { 54 | if j == len(ports)-1 { 55 | return nil, err 56 | } 57 | 58 | continue 59 | } 60 | 61 | return client, nil 62 | } 63 | } 64 | 65 | return nil, fmt.Errorf("Couldn't connect to servers %v on any common port.", mx) 66 | } 67 | 68 | func send(m Message, c *smtp.Client) error { 69 | if err := c.Mail(m.From); err != nil { 70 | return err 71 | } 72 | 73 | if err := c.Rcpt(m.To); err != nil { 74 | return err 75 | } 76 | 77 | msg, err := c.Data() 78 | if err != nil { 79 | return err 80 | } 81 | 82 | if m.Subject != "" { 83 | _, err = msg.Write([]byte("Subject: " + m.Subject + "\r\n")) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | if m.From != "" { 90 | _, err = msg.Write([]byte("From: <" + m.From + ">\r\n")) 91 | if err != nil { 92 | return err 93 | } 94 | } 95 | 96 | if m.To != "" { 97 | _, err = msg.Write([]byte("To: <" + m.To + ">\r\n")) 98 | if err != nil { 99 | return err 100 | } 101 | } 102 | 103 | _, err = fmt.Fprint(msg, m.Body) 104 | if err != nil { 105 | return err 106 | } 107 | 108 | err = msg.Close() 109 | if err != nil { 110 | return err 111 | } 112 | 113 | err = c.Quit() 114 | if err != nil { 115 | return err 116 | } 117 | 118 | return nil 119 | } 120 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/nilslice/email/email_test.go: -------------------------------------------------------------------------------- 1 | package email 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestSend(t *testing.T) { 8 | m := Message{ 9 | To: "", 10 | From: "", 11 | Subject: "", 12 | Body: "", 13 | } 14 | 15 | err := m.Send() 16 | if err != nil { 17 | t.Fatal("Send returned error:", err) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/nilslice/jwt/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2015 Steve Manuel 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/nilslice/jwt/README.md: -------------------------------------------------------------------------------- 1 | # JWT 2 | 3 | ### Usage 4 | $ go get github.com/nilslice/jwt 5 | 6 | package jwt provides methods to create and check JSON Web Tokens. It only implements HMAC 256 encryption and has a very small footprint, ideal for simple usage when authorizing clients 7 | 8 | ```go 9 | package main 10 | 11 | import ( 12 | auth "github.com/nilslice/jwt" 13 | "fmt" 14 | "net/http" 15 | "strings" 16 | ) 17 | 18 | func main() { 19 | http.HandleFunc("/auth/new", func(res http.ResponseWriter, req *http.Request) { 20 | claims := map[string]interface{}{"exp": time.Now().Add(time.Hour * 24).Unix()} 21 | token, err := auth.New(claims) 22 | if err != nil { 23 | http.Error(res, "Error", 500) 24 | return 25 | } 26 | res.Header().Add("Authorization", "Bearer "+token) 27 | 28 | res.WriteHeader(http.StatusOK) 29 | }) 30 | 31 | http.HandleFunc("/auth", func(res http.ResponseWriter, req *http.Request) { 32 | userToken := strings.Split(req.Header.Get("Authorization"), " ")[1] 33 | 34 | if auth.Passes(userToken) { 35 | fmt.Println("ok") 36 | } else { 37 | fmt.Println("no") 38 | } 39 | }) 40 | 41 | http.ListenAndServe(":8080", nil) 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/nilslice/jwt/doc.go: -------------------------------------------------------------------------------- 1 | // Package jwt provides methods to create and check JSON Web Tokens (JWT). It only implements HMAC 256 encryption and has a very small footprint, ideal for simple usage when authorizing clients 2 | /* 3 | 4 | package main 5 | 6 | import ( 7 | auth "github.com/nilslice/jwt" 8 | "fmt" 9 | "net/http" 10 | "strings" 11 | "time" 12 | ) 13 | 14 | func main() { 15 | http.HandleFunc("/auth/new", func(res http.ResponseWriter, req *http.Request) { 16 | claims := map[string]interface{}{"exp": time.Now().Add(time.Hour * 24).Unix()} 17 | token, err := auth.New(claims) 18 | if err != nil { 19 | http.Error(res, "Error", 500) 20 | return 21 | } 22 | res.Header().Add("Authorization", "Bearer "+token) 23 | 24 | res.WriteHeader(http.StatusOK) 25 | }) 26 | 27 | http.HandleFunc("/auth", func(res http.ResponseWriter, req *http.Request) { 28 | userToken := strings.Split(req.Header.Get("Authorization"), " ")[1] 29 | 30 | if auth.Passes(userToken) { 31 | fmt.Println("ok") 32 | } else { 33 | fmt.Println("no") 34 | } 35 | }) 36 | 37 | http.ListenAndServe(":8080", nil) 38 | } 39 | */ 40 | package jwt 41 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/spf13/cobra/.mailmap: -------------------------------------------------------------------------------- 1 | Steve Francia 2 | Bjørn Erik Pedersen 3 | Fabiano Franz 4 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/spf13/cobra/command_notwin.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package cobra 4 | 5 | var preExecHookFn func(*Command) 6 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/spf13/cobra/command_win.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package cobra 4 | 5 | import ( 6 | "os" 7 | "time" 8 | 9 | "github.com/inconshreveable/mousetrap" 10 | ) 11 | 12 | var preExecHookFn = preExecHook 13 | 14 | // enables an information splash screen on Windows if the CLI is started from explorer.exe. 15 | var MousetrapHelpText string = `This is a command line tool 16 | 17 | You need to open cmd.exe and run it from there. 18 | ` 19 | 20 | func preExecHook(c *Command) { 21 | if mousetrap.StartedByExplorer() { 22 | c.Print(MousetrapHelpText) 23 | time.Sleep(5 * time.Second) 24 | os.Exit(1) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/spf13/pflag/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Alex Ogier. All rights reserved. 2 | Copyright (c) 2012 The Go Authors. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Google Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/spf13/pflag/count_test.go: -------------------------------------------------------------------------------- 1 | package pflag 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | ) 7 | 8 | func setUpCount(c *int) *FlagSet { 9 | f := NewFlagSet("test", ContinueOnError) 10 | f.CountVarP(c, "verbose", "v", "a counter") 11 | return f 12 | } 13 | 14 | func TestCount(t *testing.T) { 15 | testCases := []struct { 16 | input []string 17 | success bool 18 | expected int 19 | }{ 20 | {[]string{"-vvv"}, true, 3}, 21 | {[]string{"-v", "-v", "-v"}, true, 3}, 22 | {[]string{"-v", "--verbose", "-v"}, true, 3}, 23 | {[]string{"-v=3", "-v"}, true, 4}, 24 | {[]string{"-v=a"}, false, 0}, 25 | } 26 | 27 | devnull, _ := os.Open(os.DevNull) 28 | os.Stderr = devnull 29 | for i := range testCases { 30 | var count int 31 | f := setUpCount(&count) 32 | 33 | tc := &testCases[i] 34 | 35 | err := f.Parse(tc.input) 36 | if err != nil && tc.success == true { 37 | t.Errorf("expected success, got %q", err) 38 | continue 39 | } else if err == nil && tc.success == false { 40 | t.Errorf("expected failure, got success") 41 | continue 42 | } else if tc.success { 43 | c, err := f.GetCount("verbose") 44 | if err != nil { 45 | t.Errorf("Got error trying to fetch the counter flag") 46 | } 47 | if c != tc.expected { 48 | t.Errorf("expected %q, got %q", tc.expected, c) 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/spf13/pflag/example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package pflag_test 6 | 7 | import ( 8 | "fmt" 9 | 10 | "github.com/spf13/pflag" 11 | ) 12 | 13 | func ExampleShorthandLookup() { 14 | name := "verbose" 15 | short := name[:1] 16 | 17 | pflag.BoolP(name, short, false, "verbose output") 18 | 19 | // len(short) must be == 1 20 | flag := pflag.ShorthandLookup(short) 21 | 22 | fmt.Println(flag.Name) 23 | } 24 | 25 | func ExampleFlagSet_ShorthandLookup() { 26 | name := "verbose" 27 | short := name[:1] 28 | 29 | fs := pflag.NewFlagSet("Example", pflag.ContinueOnError) 30 | fs.BoolP(name, short, false, "verbose output") 31 | 32 | // len(short) must be == 1 33 | flag := fs.ShorthandLookup(short) 34 | 35 | fmt.Println(flag.Name) 36 | } 37 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/spf13/pflag/export_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package pflag 6 | 7 | import ( 8 | "io/ioutil" 9 | "os" 10 | ) 11 | 12 | // Additional routines compiled into the package only during testing. 13 | 14 | // ResetForTesting clears all flag state and sets the usage function as directed. 15 | // After calling ResetForTesting, parse errors in flag handling will not 16 | // exit the program. 17 | func ResetForTesting(usage func()) { 18 | CommandLine = &FlagSet{ 19 | name: os.Args[0], 20 | errorHandling: ContinueOnError, 21 | output: ioutil.Discard, 22 | } 23 | Usage = usage 24 | } 25 | 26 | // GetCommandLine returns the default FlagSet. 27 | func GetCommandLine() *FlagSet { 28 | return CommandLine 29 | } 30 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/spf13/pflag/golangflag_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package pflag 6 | 7 | import ( 8 | goflag "flag" 9 | "testing" 10 | ) 11 | 12 | func TestGoflags(t *testing.T) { 13 | goflag.String("stringFlag", "stringFlag", "stringFlag") 14 | goflag.Bool("boolFlag", false, "boolFlag") 15 | 16 | f := NewFlagSet("test", ContinueOnError) 17 | 18 | f.AddGoFlagSet(goflag.CommandLine) 19 | err := f.Parse([]string{"--stringFlag=bob", "--boolFlag"}) 20 | if err != nil { 21 | t.Fatal("expected no error; get", err) 22 | } 23 | 24 | getString, err := f.GetString("stringFlag") 25 | if err != nil { 26 | t.Fatal("expected no error; get", err) 27 | } 28 | if getString != "bob" { 29 | t.Fatalf("expected getString=bob but got getString=%s", getString) 30 | } 31 | 32 | getBool, err := f.GetBool("boolFlag") 33 | if err != nil { 34 | t.Fatal("expected no error; get", err) 35 | } 36 | if getBool != true { 37 | t.Fatalf("expected getBool=true but got getBool=%v", getBool) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/spf13/pflag/ip_test.go: -------------------------------------------------------------------------------- 1 | package pflag 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "os" 7 | "testing" 8 | ) 9 | 10 | func setUpIP(ip *net.IP) *FlagSet { 11 | f := NewFlagSet("test", ContinueOnError) 12 | f.IPVar(ip, "address", net.ParseIP("0.0.0.0"), "IP Address") 13 | return f 14 | } 15 | 16 | func TestIP(t *testing.T) { 17 | testCases := []struct { 18 | input string 19 | success bool 20 | expected string 21 | }{ 22 | {"0.0.0.0", true, "0.0.0.0"}, 23 | {" 0.0.0.0 ", true, "0.0.0.0"}, 24 | {"1.2.3.4", true, "1.2.3.4"}, 25 | {"127.0.0.1", true, "127.0.0.1"}, 26 | {"255.255.255.255", true, "255.255.255.255"}, 27 | {"", false, ""}, 28 | {"0", false, ""}, 29 | {"localhost", false, ""}, 30 | {"0.0.0", false, ""}, 31 | {"0.0.0.", false, ""}, 32 | {"0.0.0.0.", false, ""}, 33 | {"0.0.0.256", false, ""}, 34 | {"0 . 0 . 0 . 0", false, ""}, 35 | } 36 | 37 | devnull, _ := os.Open(os.DevNull) 38 | os.Stderr = devnull 39 | for i := range testCases { 40 | var addr net.IP 41 | f := setUpIP(&addr) 42 | 43 | tc := &testCases[i] 44 | 45 | arg := fmt.Sprintf("--address=%s", tc.input) 46 | err := f.Parse([]string{arg}) 47 | if err != nil && tc.success == true { 48 | t.Errorf("expected success, got %q", err) 49 | continue 50 | } else if err == nil && tc.success == false { 51 | t.Errorf("expected failure") 52 | continue 53 | } else if tc.success { 54 | ip, err := f.GetIP("address") 55 | if err != nil { 56 | t.Errorf("Got error trying to fetch the IP flag: %v", err) 57 | } 58 | if ip.String() != tc.expected { 59 | t.Errorf("expected %q, got %q", tc.expected, ip.String()) 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/spf13/pflag/ipnet_test.go: -------------------------------------------------------------------------------- 1 | package pflag 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "os" 7 | "testing" 8 | ) 9 | 10 | func setUpIPNet(ip *net.IPNet) *FlagSet { 11 | f := NewFlagSet("test", ContinueOnError) 12 | _, def, _ := net.ParseCIDR("0.0.0.0/0") 13 | f.IPNetVar(ip, "address", *def, "IP Address") 14 | return f 15 | } 16 | 17 | func TestIPNet(t *testing.T) { 18 | testCases := []struct { 19 | input string 20 | success bool 21 | expected string 22 | }{ 23 | {"0.0.0.0/0", true, "0.0.0.0/0"}, 24 | {" 0.0.0.0/0 ", true, "0.0.0.0/0"}, 25 | {"1.2.3.4/8", true, "1.0.0.0/8"}, 26 | {"127.0.0.1/16", true, "127.0.0.0/16"}, 27 | {"255.255.255.255/19", true, "255.255.224.0/19"}, 28 | {"255.255.255.255/32", true, "255.255.255.255/32"}, 29 | {"", false, ""}, 30 | {"/0", false, ""}, 31 | {"0", false, ""}, 32 | {"0/0", false, ""}, 33 | {"localhost/0", false, ""}, 34 | {"0.0.0/4", false, ""}, 35 | {"0.0.0./8", false, ""}, 36 | {"0.0.0.0./12", false, ""}, 37 | {"0.0.0.256/16", false, ""}, 38 | {"0.0.0.0 /20", false, ""}, 39 | {"0.0.0.0/ 24", false, ""}, 40 | {"0 . 0 . 0 . 0 / 28", false, ""}, 41 | {"0.0.0.0/33", false, ""}, 42 | } 43 | 44 | devnull, _ := os.Open(os.DevNull) 45 | os.Stderr = devnull 46 | for i := range testCases { 47 | var addr net.IPNet 48 | f := setUpIPNet(&addr) 49 | 50 | tc := &testCases[i] 51 | 52 | arg := fmt.Sprintf("--address=%s", tc.input) 53 | err := f.Parse([]string{arg}) 54 | if err != nil && tc.success == true { 55 | t.Errorf("expected success, got %q", err) 56 | continue 57 | } else if err == nil && tc.success == false { 58 | t.Errorf("expected failure") 59 | continue 60 | } else if tc.success { 61 | ip, err := f.GetIPNet("address") 62 | if err != nil { 63 | t.Errorf("Got error trying to fetch the IP flag: %v", err) 64 | } 65 | if ip.String() != tc.expected { 66 | t.Errorf("expected %q, got %q", tc.expected, ip.String()) 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/tidwall/gjson/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Josh Baker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/tidwall/gjson/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/cmd/ponzu/vendor/github.com/tidwall/gjson/logo.png -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/tidwall/sjson/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/tidwall/sjson/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Josh Baker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/github.com/tidwall/sjson/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/cmd/ponzu/vendor/github.com/tidwall/sjson/logo.png -------------------------------------------------------------------------------- /cmd/ponzu/vendor/golang.org/x/crypto/autocert/cache_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package autocert 6 | 7 | import ( 8 | "context" 9 | "io/ioutil" 10 | "os" 11 | "path/filepath" 12 | "reflect" 13 | "testing" 14 | ) 15 | 16 | // make sure DirCache satisfies Cache interface 17 | var _ Cache = DirCache("/") 18 | 19 | func TestDirCache(t *testing.T) { 20 | dir, err := ioutil.TempDir("", "autocert") 21 | if err != nil { 22 | t.Fatal(err) 23 | } 24 | defer os.RemoveAll(dir) 25 | dir = filepath.Join(dir, "certs") // a nonexistent dir 26 | cache := DirCache(dir) 27 | ctx := context.Background() 28 | 29 | // test cache miss 30 | if _, err := cache.Get(ctx, "nonexistent"); err != ErrCacheMiss { 31 | t.Errorf("get: %v; want ErrCacheMiss", err) 32 | } 33 | 34 | // test put/get 35 | b1 := []byte{1} 36 | if err := cache.Put(ctx, "dummy", b1); err != nil { 37 | t.Fatalf("put: %v", err) 38 | } 39 | b2, err := cache.Get(ctx, "dummy") 40 | if err != nil { 41 | t.Fatalf("get: %v", err) 42 | } 43 | if !reflect.DeepEqual(b1, b2) { 44 | t.Errorf("b1 = %v; want %v", b1, b2) 45 | } 46 | name := filepath.Join(dir, "dummy") 47 | if _, err := os.Stat(name); err != nil { 48 | t.Error(err) 49 | } 50 | 51 | // test delete 52 | if err := cache.Delete(ctx, "dummy"); err != nil { 53 | t.Fatalf("delete: %v", err) 54 | } 55 | if _, err := cache.Get(ctx, "dummy"); err != ErrCacheMiss { 56 | t.Errorf("get: %v; want ErrCacheMiss", err) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/golang.org/x/crypto/autocert/example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package autocert_test 6 | 7 | import ( 8 | "crypto/tls" 9 | "fmt" 10 | "log" 11 | "net/http" 12 | 13 | "golang.org/x/crypto/acme/autocert" 14 | ) 15 | 16 | func ExampleNewListener() { 17 | mux := http.NewServeMux() 18 | mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 19 | fmt.Fprintf(w, "Hello, TLS user! Your config: %+v", r.TLS) 20 | }) 21 | log.Fatal(http.Serve(autocert.NewListener("example.com"), mux)) 22 | } 23 | 24 | func ExampleManager() { 25 | m := &autocert.Manager{ 26 | Cache: autocert.DirCache("secret-dir"), 27 | Prompt: autocert.AcceptTOS, 28 | HostPolicy: autocert.HostWhitelist("example.org"), 29 | } 30 | go http.ListenAndServe(":http", m.HTTPHandler(nil)) 31 | s := &http.Server{ 32 | Addr: ":https", 33 | TLSConfig: &tls.Config{GetCertificate: m.GetCertificate}, 34 | } 35 | s.ListenAndServeTLS("", "") 36 | } 37 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/base64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package bcrypt 6 | 7 | import "encoding/base64" 8 | 9 | const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" 10 | 11 | var bcEncoding = base64.NewEncoding(alphabet) 12 | 13 | func base64Encode(src []byte) []byte { 14 | n := bcEncoding.EncodedLen(len(src)) 15 | dst := make([]byte, n) 16 | bcEncoding.Encode(dst, src) 17 | for dst[n-1] == '=' { 18 | n-- 19 | } 20 | return dst[:n] 21 | } 22 | 23 | func base64Decode(src []byte) ([]byte, error) { 24 | numOfEquals := 4 - (len(src) % 4) 25 | for i := 0; i < numOfEquals; i++ { 26 | src = append(src, '=') 27 | } 28 | 29 | dst := make([]byte, bcEncoding.DecodedLen(len(src))) 30 | n, err := bcEncoding.Decode(dst, src) 31 | if err != nil { 32 | return nil, err 33 | } 34 | return dst[:n], nil 35 | } 36 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.7 6 | 7 | // Package ctxhttp provides helper functions for performing context-aware HTTP requests. 8 | package ctxhttp // import "golang.org/x/net/context/ctxhttp" 9 | 10 | import ( 11 | "io" 12 | "net/http" 13 | "net/url" 14 | "strings" 15 | 16 | "golang.org/x/net/context" 17 | ) 18 | 19 | // Do sends an HTTP request with the provided http.Client and returns 20 | // an HTTP response. 21 | // 22 | // If the client is nil, http.DefaultClient is used. 23 | // 24 | // The provided ctx must be non-nil. If it is canceled or times out, 25 | // ctx.Err() will be returned. 26 | func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { 27 | if client == nil { 28 | client = http.DefaultClient 29 | } 30 | resp, err := client.Do(req.WithContext(ctx)) 31 | // If we got an error, and the context has been canceled, 32 | // the context's error is probably more useful. 33 | if err != nil { 34 | select { 35 | case <-ctx.Done(): 36 | err = ctx.Err() 37 | default: 38 | } 39 | } 40 | return resp, err 41 | } 42 | 43 | // Get issues a GET request via the Do function. 44 | func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) { 45 | req, err := http.NewRequest("GET", url, nil) 46 | if err != nil { 47 | return nil, err 48 | } 49 | return Do(ctx, client, req) 50 | } 51 | 52 | // Head issues a HEAD request via the Do function. 53 | func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) { 54 | req, err := http.NewRequest("HEAD", url, nil) 55 | if err != nil { 56 | return nil, err 57 | } 58 | return Do(ctx, client, req) 59 | } 60 | 61 | // Post issues a POST request via the Do function. 62 | func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) { 63 | req, err := http.NewRequest("POST", url, body) 64 | if err != nil { 65 | return nil, err 66 | } 67 | req.Header.Set("Content-Type", bodyType) 68 | return Do(ctx, client, req) 69 | } 70 | 71 | // PostForm issues a POST request via the Do function. 72 | func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) { 73 | return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) 74 | } 75 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_17_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !plan9,go1.7 6 | 7 | package ctxhttp 8 | 9 | import ( 10 | "io" 11 | "net/http" 12 | "net/http/httptest" 13 | "testing" 14 | 15 | "context" 16 | ) 17 | 18 | func TestGo17Context(t *testing.T) { 19 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 20 | io.WriteString(w, "ok") 21 | })) 22 | ctx := context.Background() 23 | resp, err := Get(ctx, http.DefaultClient, ts.URL) 24 | if resp == nil || err != nil { 25 | t.Fatalf("error received from client: %v %v", err, resp) 26 | } 27 | resp.Body.Close() 28 | } 29 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !plan9,!go1.7 6 | 7 | package ctxhttp 8 | 9 | import ( 10 | "net" 11 | "net/http" 12 | "net/http/httptest" 13 | "sync" 14 | "testing" 15 | "time" 16 | 17 | "golang.org/x/net/context" 18 | ) 19 | 20 | // golang.org/issue/14065 21 | func TestClosesResponseBodyOnCancel(t *testing.T) { 22 | defer func() { testHookContextDoneBeforeHeaders = nop }() 23 | defer func() { testHookDoReturned = nop }() 24 | defer func() { testHookDidBodyClose = nop }() 25 | 26 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) 27 | defer ts.Close() 28 | 29 | ctx, cancel := context.WithCancel(context.Background()) 30 | 31 | // closed when Do enters select case <-ctx.Done() 32 | enteredDonePath := make(chan struct{}) 33 | 34 | testHookContextDoneBeforeHeaders = func() { 35 | close(enteredDonePath) 36 | } 37 | 38 | testHookDoReturned = func() { 39 | // We now have the result (the Flush'd headers) at least, 40 | // so we can cancel the request. 41 | cancel() 42 | 43 | // But block the client.Do goroutine from sending 44 | // until Do enters into the <-ctx.Done() path, since 45 | // otherwise if both channels are readable, select 46 | // picks a random one. 47 | <-enteredDonePath 48 | } 49 | 50 | sawBodyClose := make(chan struct{}) 51 | testHookDidBodyClose = func() { close(sawBodyClose) } 52 | 53 | tr := &http.Transport{} 54 | defer tr.CloseIdleConnections() 55 | c := &http.Client{Transport: tr} 56 | req, _ := http.NewRequest("GET", ts.URL, nil) 57 | _, doErr := Do(ctx, c, req) 58 | 59 | select { 60 | case <-sawBodyClose: 61 | case <-time.After(5 * time.Second): 62 | t.Fatal("timeout waiting for body to close") 63 | } 64 | 65 | if doErr != ctx.Err() { 66 | t.Errorf("Do error = %v; want %v", doErr, ctx.Err()) 67 | } 68 | } 69 | 70 | type noteCloseConn struct { 71 | net.Conn 72 | onceClose sync.Once 73 | closefn func() 74 | } 75 | 76 | func (c *noteCloseConn) Close() error { 77 | c.onceClose.Do(c.closefn) 78 | return c.Conn.Close() 79 | } 80 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/golang.org/x/net/context/withtimeout_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package context_test 6 | 7 | import ( 8 | "fmt" 9 | "time" 10 | 11 | "golang.org/x/net/context" 12 | ) 13 | 14 | func ExampleWithTimeout() { 15 | // Pass a context with a timeout to tell a blocking function that it 16 | // should abandon its work after the timeout elapses. 17 | ctx, _ := context.WithTimeout(context.Background(), 100*time.Millisecond) 18 | select { 19 | case <-time.After(200 * time.Millisecond): 20 | fmt.Println("overslept") 21 | case <-ctx.Done(): 22 | fmt.Println(ctx.Err()) // prints "context deadline exceeded" 23 | } 24 | // Output: 25 | // context deadline exceeded 26 | } 27 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/golang.org/x/text/transform/examples_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package transform_test 6 | 7 | import ( 8 | "fmt" 9 | "unicode" 10 | 11 | "golang.org/x/text/transform" 12 | "golang.org/x/text/unicode/norm" 13 | ) 14 | 15 | func ExampleRemoveFunc() { 16 | input := []byte(`tschüß; до свидания`) 17 | 18 | b := make([]byte, len(input)) 19 | 20 | t := transform.RemoveFunc(unicode.IsSpace) 21 | n, _, _ := t.Transform(b, input, true) 22 | fmt.Println(string(b[:n])) 23 | 24 | t = transform.RemoveFunc(func(r rune) bool { 25 | return !unicode.Is(unicode.Latin, r) 26 | }) 27 | n, _, _ = t.Transform(b, input, true) 28 | fmt.Println(string(b[:n])) 29 | 30 | n, _, _ = t.Transform(b, norm.NFD.Bytes(input), true) 31 | fmt.Println(string(b[:n])) 32 | 33 | // Output: 34 | // tschüß;досвидания 35 | // tschüß 36 | // tschuß 37 | } 38 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/golang.org/x/text/unicode/norm/example_iter_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package norm_test 6 | 7 | import ( 8 | "bytes" 9 | "fmt" 10 | "unicode/utf8" 11 | 12 | "golang.org/x/text/unicode/norm" 13 | ) 14 | 15 | // EqualSimple uses a norm.Iter to compare two non-normalized 16 | // strings for equivalence. 17 | func EqualSimple(a, b string) bool { 18 | var ia, ib norm.Iter 19 | ia.InitString(norm.NFKD, a) 20 | ib.InitString(norm.NFKD, b) 21 | for !ia.Done() && !ib.Done() { 22 | if !bytes.Equal(ia.Next(), ib.Next()) { 23 | return false 24 | } 25 | } 26 | return ia.Done() && ib.Done() 27 | } 28 | 29 | // FindPrefix finds the longest common prefix of ASCII characters 30 | // of a and b. 31 | func FindPrefix(a, b string) int { 32 | i := 0 33 | for ; i < len(a) && i < len(b) && a[i] < utf8.RuneSelf && a[i] == b[i]; i++ { 34 | } 35 | return i 36 | } 37 | 38 | // EqualOpt is like EqualSimple, but optimizes the special 39 | // case for ASCII characters. 40 | func EqualOpt(a, b string) bool { 41 | n := FindPrefix(a, b) 42 | a, b = a[n:], b[n:] 43 | var ia, ib norm.Iter 44 | ia.InitString(norm.NFKD, a) 45 | ib.InitString(norm.NFKD, b) 46 | for !ia.Done() && !ib.Done() { 47 | if !bytes.Equal(ia.Next(), ib.Next()) { 48 | return false 49 | } 50 | if n := int64(FindPrefix(a[ia.Pos():], b[ib.Pos():])); n != 0 { 51 | ia.Seek(n, 1) 52 | ib.Seek(n, 1) 53 | } 54 | } 55 | return ia.Done() && ib.Done() 56 | } 57 | 58 | var compareTests = []struct{ a, b string }{ 59 | {"aaa", "aaa"}, 60 | {"aaa", "aab"}, 61 | {"a\u0300a", "\u00E0a"}, 62 | {"a\u0300\u0320b", "a\u0320\u0300b"}, 63 | {"\u1E0A\u0323", "\x44\u0323\u0307"}, 64 | // A character that decomposes into multiple segments 65 | // spans several iterations. 66 | {"\u3304", "\u30A4\u30CB\u30F3\u30AF\u3099"}, 67 | } 68 | 69 | func ExampleIter() { 70 | for i, t := range compareTests { 71 | r0 := EqualSimple(t.a, t.b) 72 | r1 := EqualOpt(t.a, t.b) 73 | fmt.Printf("%d: %v %v\n", i, r0, r1) 74 | } 75 | // Output: 76 | // 0: true true 77 | // 1: false false 78 | // 2: true true 79 | // 3: true true 80 | // 4: true true 81 | // 5: true true 82 | } 83 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/golang.org/x/text/unicode/norm/example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package norm_test 6 | 7 | import ( 8 | "fmt" 9 | 10 | "golang.org/x/text/unicode/norm" 11 | ) 12 | 13 | func ExampleNextBoundary() { 14 | s := norm.NFD.String("Mêlée") 15 | 16 | for i := 0; i < len(s); { 17 | d := norm.NFC.NextBoundaryInString(s[i:], true) 18 | fmt.Printf("%[1]s: %+[1]q\n", s[i:i+d]) 19 | i += d 20 | } 21 | // Output: 22 | // M: "M" 23 | // ê: "e\u0302" 24 | // l: "l" 25 | // é: "e\u0301" 26 | // e: "e" 27 | } 28 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/golang.org/x/text/unicode/norm/forminfo_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build test 6 | 7 | package norm 8 | 9 | import "testing" 10 | 11 | func TestProperties(t *testing.T) { 12 | var d runeData 13 | CK := [2]string{"C", "K"} 14 | for k, r := 1, rune(0); r < 0x2ffff; r++ { 15 | if k < len(testData) && r == testData[k].r { 16 | d = testData[k] 17 | k++ 18 | } 19 | s := string(r) 20 | for j, p := range []Properties{NFC.PropertiesString(s), NFKC.PropertiesString(s)} { 21 | f := d.f[j] 22 | if p.CCC() != d.ccc { 23 | t.Errorf("%U: ccc(%s): was %d; want %d %X", r, CK[j], p.CCC(), d.ccc, p.index) 24 | } 25 | if p.isYesC() != (f.qc == Yes) { 26 | t.Errorf("%U: YesC(%s): was %v; want %v", r, CK[j], p.isYesC(), f.qc == Yes) 27 | } 28 | if p.combinesBackward() != (f.qc == Maybe) { 29 | t.Errorf("%U: combines backwards(%s): was %v; want %v", r, CK[j], p.combinesBackward(), f.qc == Maybe) 30 | } 31 | if p.nLeadingNonStarters() != d.nLead { 32 | t.Errorf("%U: nLead(%s): was %d; want %d %#v %#v", r, CK[j], p.nLeadingNonStarters(), d.nLead, p, d) 33 | } 34 | if p.nTrailingNonStarters() != d.nTrail { 35 | t.Errorf("%U: nTrail(%s): was %d; want %d %#v %#v", r, CK[j], p.nTrailingNonStarters(), d.nTrail, p, d) 36 | } 37 | if p.combinesForward() != f.combinesForward { 38 | t.Errorf("%U: combines forward(%s): was %v; want %v %#v", r, CK[j], p.combinesForward(), f.combinesForward, p) 39 | } 40 | // Skip Hangul as it is algorithmically computed. 41 | if r >= hangulBase && r < hangulEnd { 42 | continue 43 | } 44 | if p.hasDecomposition() { 45 | if has := f.decomposition != ""; !has { 46 | t.Errorf("%U: hasDecomposition(%s): was %v; want %v", r, CK[j], p.hasDecomposition(), has) 47 | } 48 | if string(p.Decomposition()) != f.decomposition { 49 | t.Errorf("%U: decomp(%s): was %+q; want %+q", r, CK[j], p.Decomposition(), f.decomposition) 50 | } 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/golang.org/x/text/unicode/norm/norm_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package norm_test 6 | 7 | import ( 8 | "testing" 9 | ) 10 | 11 | func TestPlaceHolder(t *testing.T) { 12 | // Does nothing, just allows the Makefile to be canonical 13 | // while waiting for the package itself to be written. 14 | } 15 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/golang.org/x/text/unicode/norm/readwriter_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package norm 6 | 7 | import ( 8 | "bytes" 9 | "fmt" 10 | "testing" 11 | ) 12 | 13 | var bufSizes = []int{1, 2, 3, 4, 5, 6, 7, 8, 100, 101, 102, 103, 4000, 4001, 4002, 4003} 14 | 15 | func readFunc(size int) appendFunc { 16 | return func(f Form, out []byte, s string) []byte { 17 | out = append(out, s...) 18 | r := f.Reader(bytes.NewBuffer(out)) 19 | buf := make([]byte, size) 20 | result := []byte{} 21 | for n, err := 0, error(nil); err == nil; { 22 | n, err = r.Read(buf) 23 | result = append(result, buf[:n]...) 24 | } 25 | return result 26 | } 27 | } 28 | 29 | func TestReader(t *testing.T) { 30 | for _, s := range bufSizes { 31 | name := fmt.Sprintf("TestReader%d", s) 32 | runNormTests(t, name, readFunc(s)) 33 | } 34 | } 35 | 36 | func writeFunc(size int) appendFunc { 37 | return func(f Form, out []byte, s string) []byte { 38 | in := append(out, s...) 39 | result := new(bytes.Buffer) 40 | w := f.Writer(result) 41 | buf := make([]byte, size) 42 | for n := 0; len(in) > 0; in = in[n:] { 43 | n = copy(buf, in) 44 | _, _ = w.Write(buf[:n]) 45 | } 46 | w.Close() 47 | return result.Bytes() 48 | } 49 | } 50 | 51 | func TestWriter(t *testing.T) { 52 | for _, s := range bufSizes { 53 | name := fmt.Sprintf("TestWriter%d", s) 54 | runNormTests(t, name, writeFunc(s)) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /cmd/ponzu/vendor/golang.org/x/text/unicode/norm/trie.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package norm 6 | 7 | type valueRange struct { 8 | value uint16 // header: value:stride 9 | lo, hi byte // header: lo:n 10 | } 11 | 12 | type sparseBlocks struct { 13 | values []valueRange 14 | offset []uint16 15 | } 16 | 17 | var nfcSparse = sparseBlocks{ 18 | values: nfcSparseValues[:], 19 | offset: nfcSparseOffset[:], 20 | } 21 | 22 | var nfkcSparse = sparseBlocks{ 23 | values: nfkcSparseValues[:], 24 | offset: nfkcSparseOffset[:], 25 | } 26 | 27 | var ( 28 | nfcData = newNfcTrie(0) 29 | nfkcData = newNfkcTrie(0) 30 | ) 31 | 32 | // lookupValue determines the type of block n and looks up the value for b. 33 | // For n < t.cutoff, the block is a simple lookup table. Otherwise, the block 34 | // is a list of ranges with an accompanying value. Given a matching range r, 35 | // the value for b is by r.value + (b - r.lo) * stride. 36 | func (t *sparseBlocks) lookup(n uint32, b byte) uint16 { 37 | offset := t.offset[n] 38 | header := t.values[offset] 39 | lo := offset + 1 40 | hi := lo + uint16(header.lo) 41 | for lo < hi { 42 | m := lo + (hi-lo)/2 43 | r := t.values[m] 44 | if r.lo <= b && b <= r.hi { 45 | return r.value + uint16(b-r.lo)*header.value 46 | } 47 | if b < r.lo { 48 | hi = m 49 | } else { 50 | lo = m + 1 51 | } 52 | } 53 | return 0 54 | } 55 | -------------------------------------------------------------------------------- /cmd/ponzu/version.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | "path/filepath" 9 | 10 | "github.com/spf13/cobra" 11 | ) 12 | 13 | var versionCmd = &cobra.Command{ 14 | Use: "version", 15 | Aliases: []string{"v"}, 16 | Short: "Prints the version of Ponzu your project is using.", 17 | Long: `Prints the version of Ponzu your project is using. Must be called from 18 | within a Ponzu project directory.`, 19 | Example: `$ ponzu version 20 | > Ponzu v0.8.2 21 | (or) 22 | $ ponzu version --cli 23 | > Ponzu v0.9.2`, 24 | Run: func(cmd *cobra.Command, args []string) { 25 | p, err := version(cli) 26 | if err != nil { 27 | fmt.Println(err) 28 | os.Exit(1) 29 | } 30 | 31 | fmt.Fprintf(os.Stdout, "Ponzu v%s\n", p["version"]) 32 | }, 33 | } 34 | 35 | func version(isCLI bool) (map[string]interface{}, error) { 36 | kv := make(map[string]interface{}) 37 | 38 | info := filepath.Join("cmd", "ponzu", "ponzu.json") 39 | if isCLI { 40 | gopath, err := getGOPATH() 41 | if err != nil { 42 | return nil, err 43 | } 44 | repo := filepath.Join(gopath, "src", "github.com", "ponzu-cms", "ponzu") 45 | info = filepath.Join(repo, "cmd", "ponzu", "ponzu.json") 46 | } 47 | 48 | b, err := ioutil.ReadFile(info) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | err = json.Unmarshal(b, &kv) 54 | if err != nil { 55 | return nil, err 56 | } 57 | 58 | return kv, nil 59 | } 60 | 61 | func init() { 62 | versionCmd.Flags().BoolVar(&cli, "cli", false, "specify that information should be returned about the CLI, not project") 63 | RegisterCmdlineCommand(versionCmd) 64 | } 65 | -------------------------------------------------------------------------------- /content/doc.go: -------------------------------------------------------------------------------- 1 | // Package content contains all user-supplied content which the system is to 2 | // manage. Generate content types by using the Ponzu command line tool 'ponzu' 3 | // by running `$ ponzu generate content ` 4 | // Note: doc.go file is required to build the Ponzu command since some packages 5 | // import content package to a blank identifier. 6 | package content 7 | -------------------------------------------------------------------------------- /deployment/README.md: -------------------------------------------------------------------------------- 1 | # Deployment 2 | 3 | This is a set of deployment scripts for starting up `ponzu-server` processes on 4 | system boot and run levels. 5 | 6 | To add one for a missing platform / OS, fork the ponzu repository and create a 7 | new pull request with the script inside a directory named by the corresponding 8 | init system. 9 | 10 | Questions? Reach out to [@ponzu_cms](https://twitter.com/ponzu_cms) on Twitter, 11 | or open an issue at https://github.com/ponzu-cms/ponzu 12 | -------------------------------------------------------------------------------- /deployment/sysv/ponzu-server: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: ponzu-server 4 | # Required-Start: $local_fs $network $named $time $syslog 5 | # Required-Stop: $local_fs $network $named $time $syslog 6 | # Default-Start: 2 3 4 5 7 | # Default-Stop: 0 1 6 8 | # Description: Ponzu API & Admin server 9 | ### END INIT INFO 10 | 11 | PROJECT_DIR= 12 | SCRIPT="cd $PROJECT_DIR && ponzu run --port=80" # add --https here to get TLS/HTTPS 13 | RUNAS= 14 | 15 | PIDFILE=/var/run/ponzu-server.pid 16 | LOGFILE=/var/log/ponzu-server.log 17 | 18 | start() { 19 | if [ -f /var/run/$PIDNAME ] && kill -0 $(cat /var/run/$PIDNAME); then 20 | echo 'Service already running' >&2 21 | return 1 22 | fi 23 | echo 'Starting service…' >&2 24 | local CMD="$SCRIPT &> \"$LOGFILE\" & echo \$!" 25 | su -c "$CMD" $RUNAS > "$PIDFILE" 26 | echo 'Service started' >&2 27 | } 28 | 29 | stop() { 30 | if [ ! -f "$PIDFILE" ] || ! kill -0 $(cat "$PIDFILE"); then 31 | echo 'Service not running' >&2 32 | return 1 33 | fi 34 | echo 'Stopping service…' >&2 35 | kill -15 $(cat "$PIDFILE") && rm -f "$PIDFILE" 36 | echo 'Service stopped' >&2 37 | } 38 | 39 | uninstall() { 40 | echo -n "Are you really sure you want to uninstall this service? That cannot be undone. [yes|No] " 41 | local SURE 42 | read SURE 43 | if [ "$SURE" = "yes" ]; then 44 | stop 45 | rm -f "$PIDFILE" 46 | echo "Notice: log file is not be removed: '$LOGFILE'" >&2 47 | update-rc.d -f remove 48 | rm -fv "$0" 49 | fi 50 | } 51 | 52 | case "$1" in 53 | start) 54 | start 55 | ;; 56 | stop) 57 | stop 58 | ;; 59 | uninstall) 60 | uninstall 61 | ;; 62 | restart) 63 | stop 64 | start 65 | ;; 66 | *) 67 | echo "Usage: $0 {start|stop|restart|uninstall}" 68 | esac 69 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/.gitignore -------------------------------------------------------------------------------- /docs/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2016 Boss Sauce Creative, LLC. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Ponzu CMS + Server Framerwork Docs 2 | 3 | ## Contributing 4 | 5 | Documentation contributions are welcome and appreciated. If you find something 6 | lacking in documentation or have submitted a PR that is being merged into master, 7 | please help everyone out and write some docs! 8 | 9 | **Note:** Docker is required to follow these instructions, but you can also use 10 | MkDocs natively, [see details here](http://www.mkdocs.org/#installation). Ponzu 11 | docs use the "Material" [theme](http://squidfunk.github.io/mkdocs-material/). 12 | 13 | 14 | Here is how to run a local docs server and build them for release: 15 | 16 | 1. Clone this repository 17 | ```bash 18 | $ git clone https://github.com/ponzu-cms/docs.git 19 | ``` 20 | 2. Start the development server which will watch and auto-build the docs 21 | ```bash 22 | $ docker run --rm -it -p 8000:8000 -v `pwd`:/docs squidfunk/mkdocs-material 23 | ``` 24 | 3. Submit a PR with your changes. If you run the build step, please do not add it to the PR. 25 | 26 | **Thank you!** 27 | -------------------------------------------------------------------------------- /docs/build/assets/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/build/assets/images/favicon.ico -------------------------------------------------------------------------------- /docs/build/assets/images/icons/bitbucket-670608a71a.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/build/assets/images/icons/github-1da075986e.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/build/assets/images/icons/gitlab-5ad3f9f9e5.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/build/images/editor-checkbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/build/images/editor-checkbox.png -------------------------------------------------------------------------------- /docs/build/images/editor-file-repeater.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/build/images/editor-file-repeater.png -------------------------------------------------------------------------------- /docs/build/images/editor-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/build/images/editor-file.png -------------------------------------------------------------------------------- /docs/build/images/editor-input-repeater.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/build/images/editor-input-repeater.png -------------------------------------------------------------------------------- /docs/build/images/editor-input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/build/images/editor-input.png -------------------------------------------------------------------------------- /docs/build/images/editor-richtext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/build/images/editor-richtext.png -------------------------------------------------------------------------------- /docs/build/images/editor-select-repeater.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/build/images/editor-select-repeater.png -------------------------------------------------------------------------------- /docs/build/images/editor-select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/build/images/editor-select.png -------------------------------------------------------------------------------- /docs/build/images/editor-tags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/build/images/editor-tags.png -------------------------------------------------------------------------------- /docs/build/images/editor-textarea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/build/images/editor-textarea.png -------------------------------------------------------------------------------- /docs/build/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/build/images/logo.png -------------------------------------------------------------------------------- /docs/build/images/ponzu-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/build/images/ponzu-banner.png -------------------------------------------------------------------------------- /docs/build/mkdocs/js/search-results-template.mustache: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /docs/mkdocs.yml: -------------------------------------------------------------------------------- 1 | theme: material 2 | site_name: Ponzu 3 | docs_dir: src 4 | site_dir: build 5 | repo_name: ponzu-cms/ponzu 6 | repo_url: https://github.com/ponzu-cms/ponzu 7 | 8 | markdown_extensions: 9 | - codehilite(linenums=false) 10 | - meta 11 | - admonition 12 | - toc(permalink=true) 13 | 14 | google_analytics: 15 | - 'UA-98609560-1' 16 | - auto 17 | 18 | extra: 19 | palette: 20 | primary: grey 21 | accent: light-blue 22 | social: 23 | - type: github 24 | link: https://github.com/ponzu-cms 25 | - type: twitter 26 | link: https://twitter.com/ponzu_cms 27 | logo: images/logo.png 28 | -------------------------------------------------------------------------------- /docs/src/Content/Extending-Content.md: -------------------------------------------------------------------------------- 1 | title: Extending Content through built-in Interfaces and optional Addons 2 | 3 | Extending your Content types with more features and functionality within the system 4 | is done by implementing the various built-in interfaces provided by Ponzu. To learn 5 | more about interfaces, see [A Tour of Go - Interfaces](https://tour.golang.org/methods/10). 6 | 7 | It is also common to add more advanced functionality to Content types using Addons. Refer to the [Addon documentation](/Ponzu-Addons) for more information about how to use and create Ponzu Addons. 8 | 9 | ## [Item Interfaces](/Interfaces/Item) 10 | 11 | All Content types which embed an `item.Item` will implicitly [implement](#) its many 12 | interfaces. In Ponzu, the following interfaces are exported from the `system/item` 13 | package and have a default implementation which can be overridden to change your 14 | content types' functionality within the system. 15 | 16 | - [`item.Pushable`](/Interfaces/Item#itempushable) 17 | - [`item.Hideable`](/Interfaces/Item#itemhideable) 18 | - [`item.Omittable`](/Interfaces/Item#itemomittable) 19 | - [`item.Hookable`](/Interfaces/Item#itemhookable) 20 | - [`item.Identifiable`](/Interfaces/Item#itemidentifiable) 21 | - [`item.Sortable`](/Interfaces/Item#itemsortable) 22 | - [`item.Sluggable`](/Interfaces/Item#itemsluggable) 23 | 24 | ## [API Interfaces](/Interfaces/API) 25 | 26 | To enable 3rd-party clients to interact with your Content types, you can extend your types with the API interfaces: 27 | 28 | - [`api.Createable`](/Interfaces/API/#apicreateable) 29 | - [`api.Updateable`](/Interfaces/API/#apiupdateable) 30 | - [`api.Deleteable`](/Interfaces/API/#apideleteable) 31 | - [`api.Trustable`](/Interfaces/API/#apitrustable) 32 | 33 | ## [Editor Interfaces](/Interfaces/Editor) 34 | 35 | To manage how content is edited and handled in the CMS, use the following Editor interfaces: 36 | 37 | - [`editor.Editable`](/Interfaces/Editor/#editoreditable) 38 | - [`editor.Mergeable`](/Interfaces/Editor/#editormergeable) 39 | 40 | ## [Search Interfaces](/Interfaces/Search) 41 | 42 | To enable and customize full-text search on your content types, use the following interfaces: 43 | 44 | - [`search.Searchable`](/Interfaces/Search/#searchsearchable) -------------------------------------------------------------------------------- /docs/src/HTTP-APIs/File-Metadata.md: -------------------------------------------------------------------------------- 1 | title: File Metadata HTTP API 2 | 3 | Ponzu provides a read-only HTTP API to get metadata about the files that have been uploaded to your system. As a security and bandwidth abuse precaution, the API is only queryable by "slug" which is the normalized filename of the uploaded file. 4 | 5 | --- 6 | 7 | ### Endpoints 8 | 9 | #### Get File by Slug (single item) 10 | GET `/api/uploads?slug=` 11 | 12 | ##### Sample Response 13 | ```javascript 14 | { 15 | "data": [ 16 | { 17 | "uuid": "024a5797-e064-4ee0-abe3-415cb6d3ed18", 18 | "id": 6, 19 | "slug": "filename.jpg", 20 | "timestamp": 1493926453826, // milliseconds since Unix epoch 21 | "updated": 1493926453826, 22 | "name": "filename.jpg", 23 | "path": "/api/uploads/2017/05/filename.jpg", 24 | "content_length": 357557, 25 | "content_type": "image/jpeg", 26 | } 27 | ] 28 | } 29 | ``` -------------------------------------------------------------------------------- /docs/src/HTTP-APIs/Search.md: -------------------------------------------------------------------------------- 1 | title: Full-text Search HTTP API 2 | 3 | Ponzu provides a read-only HTTP API to search the contents of your system's database. 4 | Full-text search is made possible by the use of [Bleve](http://blevesearch.com), 5 | which handles the indexing and querying. 6 | 7 | --- 8 | 9 | ### Endpoints 10 | 11 | #### Search Content 12 | 13 | GET `/api/search?type=&q=` 14 | 15 | !!! warning "Search must be enabled individually for each Content type" 16 | - Search is not on by default to protect your data in case it shouldn't be indexed and published via the API. 17 | - `SearchMapping()` is implemented with default mapping (ideal for 99% of use cases). 18 | - To enable search, add a `IndexContent() bool` method to your content type and return `true` (default implementation returns false). 19 | 20 | - `` must implement [db.Searchable](/Interfaces/Search/#searchsearchable) 21 | 22 | - Search is currently limited to single `` per request 23 | 24 | - `` documentation here: [Bleve Docs - Query String](http://www.blevesearch.com/docs/Query-String-Query/) 25 | 26 | - Search results are formatted exactly the same as standard Content API calls, so you don't need to change your client data model 27 | 28 | - Search handler will respect other interface implementations on your content, including: 29 | - [`item.Hideable`](https://godoc.org/github.com/ponzu-cms/ponzu/system/item#Hideable) 30 | - [`item.Omittable`](https://godoc.org/github.com/ponzu-cms/ponzu/system/item#Omittable) 31 | - [`item.Pushable`](https://godoc.org/github.com/ponzu-cms/ponzu/system/item#Pushable) _(Note: only the first search result will be pushed)_ 32 | 33 | ##### Sample Response 34 | ```javascript 35 | { 36 | "data": [ 37 | { 38 | "uuid": "024a5797-e064-4ee0-abe3-415cb6d3ed18", 39 | "id": 6, 40 | "slug": "item-id-024a5797-e064-4ee0-abe3-415cb6d3ed18", // customizable 41 | "timestamp": 1493926453826, // milliseconds since Unix epoch 42 | "updated": 1493926453826, 43 | // your content data..., 44 | } 45 | ] 46 | } 47 | ``` 48 | -------------------------------------------------------------------------------- /docs/src/Interfaces/Format.md: -------------------------------------------------------------------------------- 1 | title: Format Package Interfaces 2 | 3 | Ponzu provides a set of interfaces from the `management/format` package which 4 | determine how content data should be converted and formatted for exporting via 5 | the Admin interface. 6 | 7 | --- 8 | 9 | ## Interfaces 10 | 11 | ### [format.CSVFormattable](https://godoc.org/github.com/ponzu-cms/ponzu/management/format#CSVFormattable) 12 | 13 | CSVFormattable controls if an "Export" button is added to the contents view for 14 | a Content type in the CMS to export the data to CSV. If it is implemented, a 15 | button will be present beneath the "New" button per Content type. 16 | 17 | ##### Method Set 18 | 19 | ```go 20 | type CSVFormattable interface { 21 | FormatCSV() []string 22 | } 23 | ``` 24 | 25 | ##### Implementation 26 | 27 | ```go 28 | func (p *Post) FormatCSV() []string { 29 | // []string contains the JSON struct tags generated for your Content type 30 | // implementing the interface 31 | return []string{ 32 | "id", 33 | "timestamp", 34 | "slug", 35 | "title", 36 | "photos", 37 | "body", 38 | "written_by", 39 | } 40 | } 41 | ``` 42 | 43 | !!! note "FormatCSV() []string" 44 | Just like other Ponzu content extension interfaces, like `Push()`, you will 45 | return the JSON struct tags for the fields you want exported to the CSV file. 46 | These will also be the "header" row in the CSV file to give titles to the file 47 | columns. Keep in mind that all of item.Item's fields are available here as well. 48 | 49 | -------------------------------------------------------------------------------- /docs/src/Interfaces/Search.md: -------------------------------------------------------------------------------- 1 | title: Search Package Interfaces 2 | 3 | Ponzu provides a set of interfaces from the `system/search` package to enable and customize full-text search access to content in your system. **Search is not enabled by default**, and must be enabled per Content type individually. 4 | 5 | ## Interfaces 6 | 7 | ### [search.Searchable](https://godoc.org/github.com/ponzu-cms/ponzu/system/search#Searchable) 8 | Searchable determines how content is indexed and whether the system should index the content when it is created and updated or be removed from the index when content is deleted. 9 | 10 | !!! warning "" 11 | Search is **disabled** for all Content items by default. Each Content item that should be indexed and searchable must implement the `search.Searchable` interface. 12 | 13 | ##### Method Set 14 | 15 | ```go 16 | type Searchable interface { 17 | SearchMapping() (*mapping.IndexMappingImpl, error) 18 | IndexContent() bool 19 | } 20 | ``` 21 | 22 | By default, Ponzu sets up the [Bleve's](http://blevesearch.com) "default mapping", which is typically what you want for most content-based systems. This can be overridden by implementing your own `SearchMapping() (*mapping.IndexMappingImpl, error)` method on your Content type. 23 | 24 | This way, all you need to do to get full-text search is to add the `IndexContent() bool` method to each Content type you want search enabled. Return `true` from this method to enable search. 25 | 26 | 27 | ##### Example 28 | ```go 29 | // ... 30 | 31 | type Song struct { 32 | item.Item 33 | 34 | Name string `json:"name"` 35 | // ... 36 | } 37 | 38 | func (s *Song) IndexContent() bool { 39 | return true 40 | } 41 | ``` 42 | 43 | !!! tip "Indexing Existing Content" 44 | If you previously had search disabled and had already added content to your system, you will need to re-index old content items in your CMS. Otherwise, they will not show up in search queries.. This requires you to manually open each item and click 'Save'. This could be scripted and Ponzu _might_ ship with a re-indexing function at some point in the fututre. 45 | -------------------------------------------------------------------------------- /docs/src/Ponzu-Addons/Creating-Addons.md: -------------------------------------------------------------------------------- 1 | title: How to create Ponzu Addons 2 | 3 | # Coming soon 4 | 5 | For a reference to creating your own addons, see: 6 | [https://github.com/bosssauce/fbscheduler](https://github.com/bosssauce/fbscheduler) 7 | -------------------------------------------------------------------------------- /docs/src/Ponzu-Addons/Using-Addons.md: -------------------------------------------------------------------------------- 1 | title: How to use Ponzu Addons 2 | 3 | # Coming soon 4 | 5 | For a reference to creating your own addons, see: 6 | [https://github.com/bosssauce/fbscheduler](https://github.com/bosssauce/fbscheduler) 7 | -------------------------------------------------------------------------------- /docs/src/Quickstart/Overview.md: -------------------------------------------------------------------------------- 1 | ### Quickstart Steps 2 | 1) Install [Go 1.8+](https://golang.org/dl/) 3 | 4 | 2) Install Ponzu CLI: 5 | ```bash 6 | $ go get github.com/ponzu-cms/ponzu/… 7 | ``` 8 | 9 | 3) Create a new project (path is created in your GOPATH): 10 | ```bash 11 | $ ponzu new github.com/nilslice/reviews 12 | ``` 13 | 14 | 4) Enter your new project directory: 15 | ```bash 16 | $ cd $GOPATH/src/github.com/nilslice/reviews 17 | ``` 18 | 19 | 5) Generate content type file and boilerplate code (creates `content/review.go`): 20 | ```bash 21 | $ ponzu generate content review title:"string" author:"string" rating:"float64" body:"string":richtext website_url:"string" items:"[]string" photo:string:file 22 | ``` 23 | 24 | 6) Build your project: 25 | ```bash 26 | $ ponzu build 27 | ``` 28 | 29 | 7) Run your project with defaults: 30 | ```bash 31 | $ ponzu run 32 | ``` 33 | 34 | 8) Open browser to [`http://localhost:8080/admin`](http://localhost:8080/admin) 35 | 36 | ### Notes 37 | - One-time initialization to set configuration 38 | - All fields can be changed in Configuration afterward 39 | -------------------------------------------------------------------------------- /docs/src/Running-Backups/Backups.md: -------------------------------------------------------------------------------- 1 | title: Running Backups on Ponzu systems 2 | 3 | Both the databases `system.db` & `analytics.db`, and the `/uploads` directory can be backed up over HTTP using `wget`, `curl`, etc. All of which are located at the `/admin/backup` route and require HTTP Basic Auth. In order to enable backups, you must add a user/password pair inside the CMS Configuration at `/admin/configure` near the bottom of the page. 4 | 5 | All backups are made using a `GET` request to the `/admin/backup` path with a query parameter of `?source={system,analytics,uploads}` (only one source can be included in the URL). 6 | 7 | Here are some full backup scripts to use or modify to fit your needs: 8 | [https://github.com/ponzu-cms/backup-scripts](https://github.com/ponzu-cms/backup-scripts) 9 | 10 | ## System & Analytics 11 | The `system.db` & `analytics.db` data files are sent uncompressed in their original form as they exist on your server. No temporary copy is stored on the origin server, and it is possible that the backup could fail so checking for successful backups is recommended. See https://github.com/boltdb/bolt#database-backups for more information about how BoltDB handles HTTP backups. 12 | 13 | An example backup request for the `system.db` data file would look like: 14 | ```bash 15 | $ curl --user user:pass "https://example.com/admin/backup?source=system" > system.db.bak 16 | ``` 17 | 18 | ## Uploads 19 | The `uploads` directory is gzip compressed and archived as a tar file, stored in the temporary directory (typically `/tmp` on Linux) on your origin server with a timestamp in the file name. It is removed after the HTTP response for the backup has been written. 20 | 21 | An example backup request for the `/uploads` directory would look like: 22 | ```bash 23 | $ curl --user user:pass "https://example.com/admin/backup?source=uploads" > uploads.tar.gz 24 | # unarchive the tarball with gzip 25 | $ tar xzf uploads.tar.gz 26 | ``` 27 | 28 | ## Search Indexes 29 | The `search` directory, which is created to store the various search indexes for your content types (only if they implement `search.Searchable`), is backed up in the same fashion as [Uploads](/Running-Backups/Backups/#uploads). 30 | 31 | An example backup request for the `/search` directory would look like: 32 | ```bash 33 | $ curl --user user:pass "https://example.com/admin/backup?source=search" > search.tar.gz 34 | # unarchive the tarball with gzip 35 | $ tar xzf search.tar.gz 36 | ``` -------------------------------------------------------------------------------- /docs/src/System-Deployment/Docker.md: -------------------------------------------------------------------------------- 1 | ## Ponzu Docker build 2 | 3 | Ponzu is distributed as a [docker image](https://hub.docker.com/r/ponzu/ponzu/), 4 | which aids in ponzu deployment. The Dockerfile in this directory is used by Ponzu 5 | to generate the docker image which contains the ponzu executable. 6 | 7 | If you are deploying your own Ponzu project, you can write a new Dockerfile that 8 | is based from the `ponzu/ponzu` image of your choice. For example: 9 | ```docker 10 | FROM ponzu/ponzu:latest 11 | 12 | # your project set up ... 13 | # ... 14 | # ... 15 | ``` 16 | 17 | ### The following are convenient commands during development of Ponzu core: 18 | 19 | #### Build the docker image. Run from the root of the project. 20 | ```bash 21 | # from the root of ponzu: 22 | docker build -t ponzu-dev 23 | ``` 24 | 25 | #### Start the image, share the local directory and pseudo terminal (tty) into for debugging: 26 | ```bash 27 | docker run -v $(pwd):/go/src/github.com/ponzu-cms/ponzu -it ponzu-dev 28 | pwd # will output the go src directory for ponzu 29 | ponzu version # will output the ponzu version 30 | # make an edit on your local and rebuild 31 | go install ./... 32 | ``` 33 | 34 | Special thanks to [**@krismeister**](https://github.com/krismeister) for contributing this! -------------------------------------------------------------------------------- /docs/src/System-Deployment/SysV-Style.md: -------------------------------------------------------------------------------- 1 | title: Deploying Ponzu on Linux with System-V style init 2 | 3 | For reference, here is an example init script to run Ponzu servers. You must 4 | define the `PROJECT_DIR` & `RUNAS` variables by replacing `` 5 | & `` in the script below: 6 | 7 | ```bash 8 | #!/bin/sh 9 | ### BEGIN INIT INFO 10 | # Provides: ponzu-server 11 | # Required-Start: $local_fs $network $named $time $syslog 12 | # Required-Stop: $local_fs $network $named $time $syslog 13 | # Default-Start: 2 3 4 5 14 | # Default-Stop: 0 1 6 15 | # Description: Ponzu API & Admin server 16 | ### END INIT INFO 17 | 18 | PROJECT_DIR= 19 | SCRIPT='cd $PROJECT_DIR && ponzu run --port=80' # add --https here to get TLS/HTTPS 20 | RUNAS= 21 | 22 | PIDFILE=/var/run/ponzu-server.pid 23 | LOGFILE=/var/log/ponzu-server.log 24 | 25 | start() { 26 | if [ -f /var/run/$PIDNAME ] && kill -0 $(cat /var/run/$PIDNAME); then 27 | echo 'Service already running' >&2 28 | return 1 29 | fi 30 | echo 'Starting service…' >&2 31 | local CMD="$SCRIPT &> \"$LOGFILE\" & echo \$!" 32 | su -c "$CMD" $RUNAS > "$PIDFILE" 33 | echo 'Service started' >&2 34 | } 35 | 36 | stop() { 37 | if [ ! -f "$PIDFILE" ] || ! kill -0 $(cat "$PIDFILE"); then 38 | echo 'Service not running' >&2 39 | return 1 40 | fi 41 | echo 'Stopping service…' >&2 42 | kill -15 $(cat "$PIDFILE") && rm -f "$PIDFILE" 43 | echo 'Service stopped' >&2 44 | } 45 | 46 | uninstall() { 47 | echo -n "Are you really sure you want to uninstall this service? That cannot be undone. [yes|No] " 48 | local SURE 49 | read SURE 50 | if [ "$SURE" = "yes" ]; then 51 | stop 52 | rm -f "$PIDFILE" 53 | echo "Notice: log file is not be removed: '$LOGFILE'" >&2 54 | update-rc.d -f remove 55 | rm -fv "$0" 56 | fi 57 | } 58 | 59 | case "$1" in 60 | start) 61 | start 62 | ;; 63 | stop) 64 | stop 65 | ;; 66 | uninstall) 67 | uninstall 68 | ;; 69 | restart) 70 | stop 71 | start 72 | ;; 73 | *) 74 | echo "Usage: $0 {start|stop|restart|uninstall}" 75 | esac 76 | ``` -------------------------------------------------------------------------------- /docs/src/images/editor-checkbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/src/images/editor-checkbox.png -------------------------------------------------------------------------------- /docs/src/images/editor-file-repeater.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/src/images/editor-file-repeater.png -------------------------------------------------------------------------------- /docs/src/images/editor-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/src/images/editor-file.png -------------------------------------------------------------------------------- /docs/src/images/editor-input-repeater.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/src/images/editor-input-repeater.png -------------------------------------------------------------------------------- /docs/src/images/editor-input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/src/images/editor-input.png -------------------------------------------------------------------------------- /docs/src/images/editor-richtext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/src/images/editor-richtext.png -------------------------------------------------------------------------------- /docs/src/images/editor-select-repeater.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/src/images/editor-select-repeater.png -------------------------------------------------------------------------------- /docs/src/images/editor-select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/src/images/editor-select.png -------------------------------------------------------------------------------- /docs/src/images/editor-tags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/src/images/editor-tags.png -------------------------------------------------------------------------------- /docs/src/images/editor-textarea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/src/images/editor-textarea.png -------------------------------------------------------------------------------- /docs/src/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/src/images/logo.png -------------------------------------------------------------------------------- /docs/src/images/ponzu-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/docs/src/images/ponzu-banner.png -------------------------------------------------------------------------------- /docs/src/index.md: -------------------------------------------------------------------------------- 1 | # Ponzu CMS + Server Framework Docs 2 | 3 | ![Ponzu](/images/ponzu-banner.png) 4 | 5 | ## What is Ponzu? 6 | 7 | > Watch the [**video introduction**](https://www.youtube.com/watch?v=T_1ncPoLgrg) 8 | 9 | Ponzu is a powerful and efficient open-source HTTP server framework and CMS. It 10 | provides automatic, free, and secure HTTP/2 over TLS (certificates obtained via 11 | [Let's Encrypt](https://letsencrypt.org)), a useful CMS and scaffolding to generate 12 | content editors, and a fast HTTP API on which to build modern applications. 13 | 14 | Want to jump in right away? Try the [Quickstart](/Quickstart/Overview) 15 | 16 | ### Table of Contents 17 | 18 | 1. [CLI](/CLI/General-Usage/) 19 | 2. [Content](/Content/An-Overview) 20 | 3. [Form Fields](/Form-Fields/HTML-Inputs) 21 | 4. [HTTP API - Content](/HTTP-APIs/Content) 22 | 5. [HTTP API - File Metadata](/HTTP-APIs/File-Metadata) 23 | 6. [HTTP API - Search](/HTTP-APIs/Search) 24 | 7. [Interfaces - API](/Interfaces/API) 25 | 8. [Interfaces - Editor](/Interfaces/Editor) 26 | 9. [Interfaces - Item](/Interfaces/Item) 27 | 10. [Interfaces - Search](/Interfaces/Search) 28 | 11. [Creating Ponzu Addons](/Ponzu-Addons/Creating-Addons) 29 | 12. [Using Ponzu Addons](/Ponzu-Addons/Using-Addons) 30 | 13. [Quickstart](/Quickstart/Overview) 31 | 14. [Backups](/Running-Backups/Backups) 32 | 15. [System Configuration](/System-Configuration/Settings) 33 | 34 | 35 | ### Need help? Get in touch 36 | - Chat: [#ponzu on Slack](https://gophers.slack.com/messages/C3TBV356D) 37 | - Reach out on Twitter: [@ponzu_cms](https://twitter.com/ponzu_cms) 38 | - File an [issue](https://github.com/ponzu-cms/ponzu/issues) 39 | 40 | --- 41 | current version: `v0.9.4` @ ponzu:master 42 | -------------------------------------------------------------------------------- /examples/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2016 Boss Sauce Creative, LLC. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | ## Examples 2 | 3 | Within this directory, you can find a number of different partial examples which 4 | show how to use Ponzu and its features. The goal of this directory is not to host 5 | full Ponzu projects, but rather just a few files or a package to demonstrate interface 6 | implementation, using hooks, adding new API endpoints, or creating/using addons. 7 | 8 | For full-project examples, please see the [`ponzu-cms/examples`](https://github.com/ponzu-cms/examples) repo. 9 | 10 | If you are making a contribution to the Ponzu project and are introducing a new 11 | feature, it would be very helpful to include an example with a concrete use-case 12 | for this directory. 13 | 14 | ### Table of Contents 15 | 1. [Create content via HTTP API using the `api.Createable` interface](https://github.com/ponzu-cms/ponzu/tree/master/examples/createable) 16 | 2. [Update content via HTTP API using the `api.Updateable` interface](https://github.com/ponzu-cms/ponzu/tree/master/examples/updateable) 17 | 3. [Delete content via HTTP API using the `api.Deleteable` interface](https://github.com/ponzu-cms/ponzu/tree/master/examples/deleteable) 18 | -------------------------------------------------------------------------------- /examples/createable/README.md: -------------------------------------------------------------------------------- 1 | # Createable 2 | 3 | This example shows how to enable outside clients to submit content to your CMS. 4 | All content submitted must be done through a POST request encoded as `multipart/form-data` 5 | to the API endpoint `/api/content/create?type=` 6 | 7 | ## Song example 8 | Imagine an app that lets users add Spotify music to a global playlist, and you need them 9 | to supply songs in the format: 10 | ```go 11 | type Song struct { 12 | item.Item 13 | 14 | Title string `json:"title"` 15 | Artist string `json:"artist"` 16 | Rating int `json:"rating"` 17 | Opinion string `json:"opinion"` 18 | SpotifyURL string `json:"spotify_url"` 19 | } 20 | ``` 21 | 22 | See the file `content/song.go` and read the comments to understand the various 23 | methods needed to satisfy required interfaces for this kind of activity. 24 | 25 | ### Overview 26 | 1. Implement `api.Createable` with the `Create(http.ResponseWriter, *http.Request) error` method to allow outside POST requests 27 | 2. Implement `editor.Mergeable` with the `Approve(http.ResponseWriter, *http.Request) error` method so you can control the Approval / Rejection of submitted content OR 28 | 3. Implement `api.Trustable` with the `AutoApprove(http.ResponseWriter, *http.Request) error` method to bypass `Approve` and auto-approve and publish submitted content 29 | 30 | There are various validation and request checks shown in this example as well. 31 | Please feel free to modify and submit a PR for updates or bug fixes! -------------------------------------------------------------------------------- /examples/deleteable/README.md: -------------------------------------------------------------------------------- 1 | # Deleteable 2 | 3 | This example shows how to enable outside clients to delete content from your CMS. 4 | All content deletes must be done through a POST request encoded as `multipart/form-data` 5 | to the API endpoint `/api/content/delete?type=&id=` 6 | 7 | ## Song example 8 | Imagine an app that lets users add Spotify music to a global playlist, and you need them 9 | to supply or remove songs which are in the format: 10 | ```go 11 | type Song struct { 12 | item.Item 13 | 14 | Title string `json:"title"` 15 | Artist string `json:"artist"` 16 | Rating int `json:"rating"` 17 | Opinion string `json:"opinion"` 18 | SpotifyURL string `json:"spotify_url"` 19 | } 20 | ``` 21 | 22 | See the file `content/song.go` and read the comments to understand the various 23 | methods needed to satisfy required interfaces for this kind of activity. 24 | 25 | ### Overview 26 | 1. Implement `api.Deleteable` with the `Delete(http.ResponseWriter, *http.Request)` method to allow outside POST requests. 27 | 2. Consistent with the createable example, authentication can be validated in `BeforeAPIDelete(http.ResponseWriter, *http.Request) error` 28 | 29 | There are various validation and request checks shown in this example as well. 30 | Please feel free to modify and submit a PR for updates or bug fixes! 31 | 32 | -------------------------------------------------------------------------------- /examples/updateable/README.md: -------------------------------------------------------------------------------- 1 | # Updateable 2 | 3 | This example shows how to enable outside clients to update content to your CMS. 4 | All content submitted must be done through a POST request encoded as `multipart/form-data` 5 | to the API endpoint `/api/content/update?type=&id=` 6 | 7 | ## Song example 8 | Imagine an app that lets users add Spotify music to a global playlist, and you need them 9 | to supply songs in the format: 10 | ```go 11 | type Song struct { 12 | item.Item 13 | 14 | Title string `json:"title"` 15 | Artist string `json:"artist"` 16 | Rating int `json:"rating"` 17 | Opinion string `json:"opinion"` 18 | SpotifyURL string `json:"spotify_url"` 19 | } 20 | ``` 21 | 22 | See the file `content/song.go` and read the comments to understand the various 23 | methods needed to satisfy required interfaces for this kind of activity. 24 | 25 | ### Overview 26 | 1. Implement `api.Updateable` with the `Update(http.ResponseWriter, *http.Request) error` method to allow outside POST requests. 27 | 2. Consistent with the createable example, authentication can be validated in `BeforeAPIUpdate(http.ResponseWriter, *http.Request) error` 28 | 29 | There are various validation and request checks shown in this example as well. 30 | Please feel free to modify and submit a PR for updates or bug fixes! 31 | 32 | -------------------------------------------------------------------------------- /management/format/csv.go: -------------------------------------------------------------------------------- 1 | // Package format provides interfaces to format content into various kinds of 2 | // data 3 | package format 4 | 5 | // CSVFormattable is implemented with the method FormatCSV, which must return the ordered 6 | // slice of JSON struct tag names for the type implmenting it 7 | type CSVFormattable interface { 8 | FormatCSV() []string 9 | } 10 | -------------------------------------------------------------------------------- /ponzu-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/ponzu-banner.png -------------------------------------------------------------------------------- /system/addon/api.go: -------------------------------------------------------------------------------- 1 | // Package addon provides an API for Ponzu addons to interface with the system 2 | package addon 3 | 4 | import ( 5 | "bytes" 6 | "fmt" 7 | "io/ioutil" 8 | "log" 9 | "net/http" 10 | "time" 11 | 12 | "github.com/ponzu-cms/ponzu/system/db" 13 | ) 14 | 15 | // QueryOptions is a mirror of the same struct in db package and are re-declared 16 | // here only to make the API simpler for the caller 17 | type QueryOptions db.QueryOptions 18 | 19 | // ContentAll retrives all items from the HTTP API within the provided namespace 20 | func ContentAll(namespace string) []byte { 21 | addr := db.ConfigCache("bind_addr").(string) 22 | port := db.ConfigCache("http_port").(string) 23 | endpoint := "http://%s:%s/api/contents?type=%s&count=-1" 24 | URL := fmt.Sprintf(endpoint, addr, port, namespace) 25 | 26 | j, err := Get(URL) 27 | if err != nil { 28 | log.Println("Error in ContentAll for reference HTTP request:", URL) 29 | return nil 30 | } 31 | 32 | return j 33 | } 34 | 35 | // Query retrieves a set of content from the HTTP API based on options 36 | // and returns the total number of content in the namespace and the content 37 | func Query(namespace string, opts QueryOptions) []byte { 38 | addr := db.ConfigCache("bind_addr").(string) 39 | port := db.ConfigCache("http_port").(string) 40 | endpoint := "http://%s:%s/api/contents?type=%s&count=%d&offset=%d&order=%s" 41 | URL := fmt.Sprintf(endpoint, addr, port, namespace, opts.Count, opts.Offset, opts.Order) 42 | 43 | j, err := Get(URL) 44 | if err != nil { 45 | log.Println("Error in Query for reference HTTP request:", URL) 46 | return nil 47 | } 48 | 49 | return j 50 | } 51 | 52 | // Get is a helper function to make a HTTP call from an addon 53 | func Get(endpoint string) ([]byte, error) { 54 | buf := []byte{} 55 | r := bytes.NewReader(buf) 56 | 57 | req, err := http.NewRequest(http.MethodGet, endpoint, r) 58 | if err != nil { 59 | log.Println("Error creating reference HTTP request:", endpoint) 60 | return nil, err 61 | } 62 | 63 | c := http.Client{ 64 | Timeout: time.Duration(time.Second * 5), 65 | } 66 | res, err := c.Do(req) 67 | if err != nil { 68 | log.Println("Error making reference HTTP request:", endpoint) 69 | return nil, err 70 | } 71 | defer res.Body.Close() 72 | 73 | j, err := ioutil.ReadAll(res.Body) 74 | if err != nil { 75 | log.Println("Error reading body for reference HTTP request:", endpoint) 76 | return nil, err 77 | } 78 | 79 | return j, nil 80 | } 81 | -------------------------------------------------------------------------------- /system/admin/filesystem.go: -------------------------------------------------------------------------------- 1 | package admin 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | "os" 7 | "path/filepath" 8 | "strings" 9 | 10 | "github.com/ponzu-cms/ponzu/system/db" 11 | "github.com/ponzu-cms/ponzu/system/item" 12 | ) 13 | 14 | func deleteUploadFromDisk(target string) error { 15 | // get data on file 16 | data, err := db.Upload(target) 17 | if err != nil { 18 | return err 19 | } 20 | 21 | // unmarshal data 22 | upload := item.FileUpload{} 23 | if err = json.Unmarshal(data, &upload); err != nil { 24 | return err 25 | } 26 | 27 | // split and rebuild path in OS friendly way 28 | // use path to delete the physical file from disk 29 | pathSplit := strings.Split(strings.TrimPrefix(upload.Path, "/api/"), "/") 30 | pathJoin := filepath.Join(pathSplit...) 31 | err = os.Remove(pathJoin) 32 | if err != nil { 33 | return err 34 | } 35 | 36 | return nil 37 | } 38 | 39 | func restrict(dir http.Dir) justFilesFilesystem { 40 | return justFilesFilesystem{dir} 41 | } 42 | 43 | // the code below removes the open directory listing when accessing a URL which 44 | // normally would point to a directory. code from golang-nuts mailing list: 45 | // https://groups.google.com/d/msg/golang-nuts/bStLPdIVM6w/hidTJgDZpHcJ 46 | // credit: Brad Fitzpatrick (c) 2012 47 | 48 | type justFilesFilesystem struct { 49 | fs http.FileSystem 50 | } 51 | 52 | func (fs justFilesFilesystem) Open(name string) (http.File, error) { 53 | f, err := fs.fs.Open(name) 54 | if err != nil { 55 | return nil, err 56 | } 57 | return neuteredReaddirFile{f}, nil 58 | } 59 | 60 | type neuteredReaddirFile struct { 61 | http.File 62 | } 63 | 64 | func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) { 65 | return nil, nil 66 | } 67 | -------------------------------------------------------------------------------- /system/admin/static/common/js/util.js: -------------------------------------------------------------------------------- 1 | // Replaces commonly-used Windows 1252 encoded chars that do not exist in ASCII or ISO-8859-1 with ISO-8859-1 cognates. 2 | // modified from http://www.andornot.com/blog/post/Replace-MS-Word-special-characters-in-javascript-and-C.aspx 3 | function replaceBadChars(text) { 4 | var s = text; 5 | // smart single quotes and apostrophe 6 | s = s.replace(/[\u2018\u2019\u201A]/g, "\'"); 7 | // smart double quotes 8 | s = s.replace(/[\u201C\u201D\u201E]/g, "\""); 9 | // ellipsis 10 | s = s.replace(/\u2026/g, "..."); 11 | // circumflex 12 | s = s.replace(/\u02C6/g, "^"); 13 | // open angle bracket 14 | s = s.replace(/\u2039/g, "<"); 15 | // close angle bracket 16 | s = s.replace(/\u203A/g, ">"); 17 | // spaces 18 | s = s.replace(/[\u02DC\u00A0]/g, " "); 19 | 20 | return s; 21 | } 22 | 23 | 24 | // Returns a local partial time object based on unix timestamp 25 | function getPartialTime(unix) { 26 | var date = new Date(unix); 27 | var t = {}; 28 | var hours = date.getHours(); 29 | if (hours < 10) { 30 | hours = "0" + String(hours); 31 | } 32 | 33 | t.hh = hours; 34 | if (hours > 12) { 35 | t.hh = hours - 12; 36 | t.pd = "PM"; 37 | } else if (hours === 12) { 38 | t.pd = "PM"; 39 | } else if (hours < 12) { 40 | t.pd = "AM"; 41 | } 42 | 43 | var minutes = date.getMinutes(); 44 | if (minutes < 10) { 45 | minutes = "0" + String(minutes); 46 | } 47 | t.mm = minutes; 48 | 49 | return t; 50 | } 51 | 52 | // Returns a local partial date object based on unix timestamp 53 | function getPartialDate(unix) { 54 | var date = new Date(unix); 55 | var d = {}; 56 | 57 | d.yyyy = date.getFullYear(); 58 | 59 | d.mm = date.getMonth()+1; 60 | 61 | var day = date.getDate(); 62 | if (day < 10) { 63 | day = "0" + String(day); 64 | } 65 | d.dd = day; 66 | 67 | return d; 68 | } 69 | 70 | // Returns a part of the window URL 'search' string 71 | function getParam(param) { 72 | var qs = window.location.search.substring(1); 73 | var qp = qs.split('&'); 74 | var t = ''; 75 | 76 | for (var i = 0; i < qp.length; i++) { 77 | var p = qp[i].split('=') 78 | if (p[0] === param) { 79 | t = p[1]; 80 | } 81 | } 82 | 83 | return t; 84 | } -------------------------------------------------------------------------------- /system/admin/static/dashboard/css/material-icons.css: -------------------------------------------------------------------------------- 1 | /* fallback */ 2 | @font-face { 3 | font-family: 'Material Icons'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: local('Material Icons'), local('MaterialIcons-Regular'), url('../fonts/icons-regular.woff2') format('woff2'); 7 | } 8 | 9 | .material-icons { 10 | font-family: 'Material Icons'; 11 | font-weight: normal; 12 | font-style: normal; 13 | font-size: 24px; 14 | line-height: 1; 15 | letter-spacing: normal; 16 | text-transform: none; 17 | display: inline-block; 18 | white-space: nowrap; 19 | word-wrap: normal; 20 | direction: ltr; 21 | -webkit-font-feature-settings: 'liga'; 22 | -webkit-font-smoothing: antialiased; 23 | } -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/icons-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/icons-regular.woff2 -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Bold.eot -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Bold.ttf -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Bold.woff -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Bold.woff2 -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Light.eot -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Light.ttf -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Light.woff -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Light.woff2 -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Medium.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Medium.eot -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Medium.ttf -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Medium.woff -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Medium.woff2 -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Regular.eot -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Regular.ttf -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Regular.woff -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Regular.woff2 -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Thin.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Thin.eot -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Thin.ttf -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Thin.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Thin.woff -------------------------------------------------------------------------------- /system/admin/static/dashboard/fonts/roboto/Roboto-Thin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/fonts/roboto/Roboto-Thin.woff2 -------------------------------------------------------------------------------- /system/admin/static/dashboard/img/ponzu-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/dashboard/img/ponzu-file.png -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Bold.ttf -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Bold.woff -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Bold.woff2 -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Light.ttf -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Light.woff -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Light.woff2 -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Medium.ttf -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Medium.woff -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Medium.woff2 -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Regular.ttf -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Regular.woff -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Regular.woff2 -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Thin.ttf -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Thin.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Thin.woff -------------------------------------------------------------------------------- /system/admin/static/editor/font/roboto/Roboto-Thin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ponzu-cms/ponzu/9bc41b703131aa42ca64265ab6fdeadc37841e66/system/admin/static/editor/font/roboto/Roboto-Thin.woff2 -------------------------------------------------------------------------------- /system/admin/static/editor/license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 CK 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 13 | all 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 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /system/admin/static/editor/sass/components/_collapsible.scss: -------------------------------------------------------------------------------- 1 | .collapsible { 2 | border-top: 1px solid $collapsible-border-color; 3 | border-right: 1px solid $collapsible-border-color; 4 | border-left: 1px solid $collapsible-border-color; 5 | margin: $element-top-margin 0 $element-bottom-margin 0; 6 | @extend .z-depth-1; 7 | } 8 | 9 | .collapsible-header { 10 | display: block; 11 | cursor: pointer; 12 | height: $collapsible-height; 13 | line-height: $collapsible-height; 14 | padding: 0 1rem; 15 | background-color: $collapsible-header-color; 16 | border-bottom: 1px solid $collapsible-border-color; 17 | 18 | i { 19 | width: 2rem; 20 | font-size: 1.6rem; 21 | line-height: $collapsible-height; 22 | display: block; 23 | float: left; 24 | text-align: center; 25 | margin-right: 1rem; 26 | } 27 | } 28 | 29 | .collapsible-body { 30 | display: none; 31 | border-bottom: 1px solid $collapsible-border-color; 32 | @include box-sizing(border-box); 33 | 34 | p { 35 | margin: 0; 36 | padding: 2rem; 37 | } 38 | } 39 | 40 | // sideNav collapsible styling 41 | .side-nav { 42 | 43 | .collapsible { 44 | border: none; 45 | box-shadow: none; 46 | 47 | li { padding: 0; } 48 | } 49 | 50 | .collapsible-header { 51 | background-color: transparent; 52 | border: none; 53 | line-height: inherit; 54 | height: inherit; 55 | margin: 0 1rem; 56 | 57 | i { line-height: inherit; } 58 | } 59 | 60 | .collapsible-body { 61 | border: 0; 62 | background-color: $collapsible-header-color; 63 | 64 | li a { margin: 0 1rem 0 2rem; } 65 | } 66 | 67 | } 68 | 69 | // Popout Collapsible 70 | 71 | .collapsible.popout { 72 | border: none; 73 | box-shadow: none; 74 | > li { 75 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); 76 | // transform: scaleX(.92); 77 | margin: 0 24px; 78 | transition: margin .35s cubic-bezier(0.250, 0.460, 0.450, 0.940); 79 | } 80 | > li.active { 81 | box-shadow: 0 5px 11px 0 rgba(0, 0, 0, 0.18), 0 4px 15px 0 rgba(0, 0, 0, 0.15); 82 | margin: 16px 0; 83 | // transform: scaleX(1); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /system/admin/static/editor/sass/components/_dropdown.scss: -------------------------------------------------------------------------------- 1 | .dropdown-content { 2 | @extend .z-depth-1; 3 | background-color: $dropdown-bg-color; 4 | margin: 0; 5 | display: none; 6 | min-width: 100px; 7 | max-height: 650px; 8 | overflow-y: auto; 9 | opacity: 0; 10 | position: absolute; 11 | z-index: 999; 12 | will-change: width, height; 13 | 14 | li { 15 | clear: both; 16 | color: $off-black; 17 | cursor: pointer; 18 | line-height: 1.5rem; 19 | width: 100%; 20 | text-align: left; 21 | text-transform: none; 22 | 23 | &:hover, &.active { 24 | background-color: $dropdown-hover-bg-color; 25 | } 26 | 27 | & > a, & > span { 28 | font-size: 1.2rem; 29 | color: $dropdown-color; 30 | display: block; 31 | padding: 1rem 1rem; 32 | } 33 | 34 | // Icon alignment override 35 | & > a > i { 36 | height: inherit; 37 | line-height: inherit; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /system/admin/static/editor/sass/components/_materialbox.scss: -------------------------------------------------------------------------------- 1 | .materialboxed { 2 | cursor: zoom-in; 3 | position: relative; 4 | @include transition(opacity .4s); 5 | 6 | &:hover { 7 | &:not(.active) { 8 | opacity: .8; 9 | } 10 | will-change: left, top, width, height; 11 | } 12 | } 13 | 14 | .materialboxed.active { 15 | cursor: zoom-out; 16 | } 17 | 18 | #materialbox-overlay { 19 | position:fixed; 20 | top:0; 21 | left:0; 22 | right: 0; 23 | bottom: 0; 24 | background-color: #292929; 25 | z-index: 999; 26 | 27 | will-change: opacity; 28 | } 29 | .materialbox-caption { 30 | position: fixed; 31 | display: none; 32 | color: #fff; 33 | line-height: 50px; 34 | bottom: 0; 35 | width: 100%; 36 | text-align: center; 37 | padding: 0% 15%; 38 | height: 50px; 39 | z-index: 1000; 40 | -webkit-font-smoothing: antialiased; 41 | } -------------------------------------------------------------------------------- /system/admin/static/editor/sass/components/_mixins.scss: -------------------------------------------------------------------------------- 1 | @mixin box-shadow-2($args1, $args2) { 2 | -webkit-box-shadow: $args1, $args2; 3 | -moz-box-shadow: $args1, $args2; 4 | box-shadow: $args1, $args2; 5 | } -------------------------------------------------------------------------------- /system/admin/static/editor/sass/components/_modal.scss: -------------------------------------------------------------------------------- 1 | .modal { 2 | @extend .z-depth-4; 3 | 4 | display: none; 5 | position: fixed; 6 | left: 0; 7 | right: 0; 8 | background-color: #fafafa; 9 | padding: 0; 10 | max-height: 70%; 11 | width: 55%; 12 | margin: auto; 13 | overflow-y: auto; 14 | 15 | border-radius: 2px; 16 | will-change: top, opacity; 17 | 18 | @media #{$medium-and-down} { 19 | width: 80%; 20 | } 21 | 22 | h1,h2,h3,h4 { 23 | margin-top: 0; 24 | } 25 | 26 | .modal-content { 27 | padding: 24px; 28 | } 29 | .modal-close { 30 | cursor: pointer; 31 | } 32 | 33 | .modal-footer { 34 | border-radius: 0 0 2px 2px; 35 | background-color: #fafafa; 36 | padding: 4px 6px; 37 | height: 56px; 38 | width: 100%; 39 | 40 | .btn, .btn-flat { 41 | float: right; 42 | margin: 6px 0; 43 | } 44 | } 45 | } 46 | .lean-overlay { 47 | position: fixed; 48 | z-index:999; 49 | top: -100px; 50 | left: 0; 51 | bottom: 0; 52 | right: 0; 53 | height: 125%; 54 | width: 100%; 55 | background: #000; 56 | display: none; 57 | 58 | will-change: opacity; 59 | } 60 | 61 | // Modal with fixed action footer 62 | .modal.modal-fixed-footer { 63 | padding: 0; 64 | height: 70%; 65 | 66 | .modal-content { 67 | position: absolute; 68 | height: calc(100% - 56px); 69 | max-height: 100%; 70 | width: 100%; 71 | overflow-y: auto; 72 | } 73 | 74 | .modal-footer { 75 | border-top: 1px solid rgba(0,0,0,.1); 76 | position: absolute; 77 | bottom: 0; 78 | } 79 | } 80 | 81 | // Modal Bottom Sheet Style 82 | .modal.bottom-sheet { 83 | top: auto; 84 | bottom: -100%; 85 | margin: 0; 86 | width: 100%; 87 | max-height: 45%; 88 | border-radius: 0; 89 | will-change: bottom, opacity; 90 | } 91 | -------------------------------------------------------------------------------- /system/admin/static/editor/sass/components/_roboto.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "Roboto"; 3 | src: url("#{$roboto-font-path}Roboto-Thin.woff2") format("woff2"), 4 | url("#{$roboto-font-path}Roboto-Thin.woff") format("woff"), 5 | url("#{$roboto-font-path}Roboto-Thin.ttf") format("truetype"); 6 | font-weight: 200; 7 | } 8 | @font-face { 9 | font-family: "Roboto"; 10 | src: url("#{$roboto-font-path}Roboto-Light.woff2") format("woff2"), 11 | url("#{$roboto-font-path}Roboto-Light.woff") format("woff"), 12 | url("#{$roboto-font-path}Roboto-Light.ttf") format("truetype"); 13 | font-weight: 300; 14 | } 15 | 16 | @font-face { 17 | font-family: "Roboto"; 18 | src: url("#{$roboto-font-path}Roboto-Regular.woff2") format("woff2"), 19 | url("#{$roboto-font-path}Roboto-Regular.woff") format("woff"), 20 | url("#{$roboto-font-path}Roboto-Regular.ttf") format("truetype"); 21 | font-weight: 400; 22 | } 23 | 24 | @font-face { 25 | font-family: "Roboto"; 26 | src: url("#{$roboto-font-path}Roboto-Medium.woff2") format("woff2"), 27 | url("#{$roboto-font-path}Roboto-Medium.woff") format("woff"), 28 | url("#{$roboto-font-path}Roboto-Medium.ttf") format("truetype"); 29 | font-weight: 500; 30 | } 31 | 32 | @font-face { 33 | font-family: "Roboto"; 34 | src: url("#{$roboto-font-path}Roboto-Bold.woff2") format("woff2"), 35 | url("#{$roboto-font-path}Roboto-Bold.woff") format("woff"), 36 | url("#{$roboto-font-path}Roboto-Bold.ttf") format("truetype"); 37 | font-weight: 700; 38 | } -------------------------------------------------------------------------------- /system/admin/static/editor/sass/components/_sideNav.scss: -------------------------------------------------------------------------------- 1 | .side-nav { 2 | position: fixed; 3 | width: 240px; 4 | left: -105%; 5 | top: 0; 6 | margin: 0; 7 | height: 100%; 8 | height: calc(100% + 60px); 9 | height: -moz-calc(100%); //Temporary Firefox Fix 10 | padding-bottom: 60px; 11 | background-color: $sidenav-bg-color; 12 | z-index: 999; 13 | overflow-y: auto; 14 | 15 | @extend .z-depth-1; 16 | will-change: left; 17 | 18 | // Right Align 19 | &.right-aligned { 20 | will-change: right; 21 | right: -105%; 22 | left: auto; 23 | } 24 | 25 | .collapsible{ 26 | margin: 0; 27 | } 28 | 29 | 30 | li { 31 | float: none; 32 | padding: 0 $sidenav-padding-right; 33 | &:hover, &.active { background-color: #ddd; } 34 | } 35 | a { 36 | color: #444; 37 | display: block; 38 | font-size: 1rem; 39 | height: 64px; 40 | line-height: 64px; 41 | padding: 0 $sidenav-padding-right; 42 | } 43 | } 44 | 45 | 46 | // Touch interaction 47 | .drag-target { 48 | height: 100%; 49 | width: 10px; 50 | position: fixed; 51 | top: 0; 52 | z-index: 998; 53 | } 54 | 55 | 56 | // Hidden side-nav for all sizes 57 | .side-nav.fixed { 58 | a { 59 | display: block; 60 | padding: 0 $sidenav-padding-right; 61 | color: #444; 62 | } 63 | } 64 | 65 | 66 | // Fixed side-nav shown 67 | .side-nav.fixed { 68 | left: 0; 69 | position: fixed; 70 | 71 | // Right Align 72 | &.right-aligned { 73 | right: 0; 74 | left: auto; 75 | } 76 | } 77 | 78 | // Fixed sideNav hide on smaller 79 | @media #{$medium-and-down} { 80 | .side-nav.fixed { 81 | left: -105%; 82 | 83 | &.right-aligned { 84 | right: -105%; 85 | left: auto; 86 | } 87 | } 88 | } 89 | 90 | 91 | .side-nav .collapsible-body li.active, 92 | .side-nav.fixed .collapsible-body li.active { 93 | background-color: $primary-color; 94 | a { 95 | color: $sidenav-bg-color; 96 | } 97 | } 98 | 99 | 100 | #sidenav-overlay { 101 | position: fixed; 102 | top: 0; 103 | left: 0; 104 | right: 0; 105 | 106 | height: 120vh; 107 | background-color: rgba(0,0,0,.5); 108 | z-index: 997; 109 | 110 | will-change: opacity; 111 | } 112 | -------------------------------------------------------------------------------- /system/admin/static/editor/sass/components/_slider.scss: -------------------------------------------------------------------------------- 1 | .slider { 2 | position: relative; 3 | height: 400px; 4 | width: 100%; 5 | 6 | // Fullscreen slider 7 | &.fullscreen { 8 | height: 100%; 9 | width: 100%; 10 | position: absolute; 11 | top: 0; 12 | left: 0; 13 | right: 0; 14 | bottom: 0; 15 | 16 | ul.slides { 17 | height: 100%; 18 | } 19 | 20 | ul.indicators { 21 | z-index: 2; 22 | bottom: 30px; 23 | } 24 | } 25 | 26 | .slides { 27 | background-color: $slider-bg-color; 28 | margin: 0; 29 | height: 400px; 30 | 31 | li { 32 | opacity: 0; 33 | position: absolute; 34 | top: 0; 35 | left: 0; 36 | z-index: 1; 37 | width: 100%; 38 | height: inherit; 39 | overflow: hidden; 40 | 41 | img { 42 | height: 100%; 43 | width: 100%; 44 | background-size: cover; 45 | background-position: center; 46 | } 47 | 48 | .caption { 49 | color: #fff; 50 | position: absolute; 51 | top: 15%; 52 | left: 15%; 53 | width: 70%; 54 | opacity: 0; 55 | 56 | p { color: $slider-bg-color-light; } 57 | } 58 | 59 | &.active { 60 | z-index: 2; 61 | } 62 | } 63 | } 64 | 65 | 66 | .indicators { 67 | position: absolute; 68 | text-align: center; 69 | left: 0; 70 | right: 0; 71 | bottom: 0; 72 | margin: 0; 73 | 74 | .indicator-item { 75 | display: inline-block; 76 | position: relative; 77 | cursor: pointer; 78 | height: 16px; 79 | width: 16px; 80 | margin: 0 12px; 81 | background-color: $slider-bg-color-light; 82 | 83 | @include transition(background-color .3s); 84 | border-radius: 50%; 85 | 86 | &.active { 87 | background-color: $slider-indicator-color; 88 | } 89 | } 90 | } 91 | 92 | } -------------------------------------------------------------------------------- /system/admin/static/editor/sass/components/_table_of_contents.scss: -------------------------------------------------------------------------------- 1 | /*************** 2 | Nav List 3 | ***************/ 4 | .table-of-contents { 5 | &.fixed { 6 | position: fixed; 7 | } 8 | 9 | li { 10 | padding: 2px 0; 11 | } 12 | a { 13 | display: inline-block; 14 | font-weight: 300; 15 | color: #757575; 16 | padding-left: 20px; 17 | height: 1.5rem; 18 | line-height: 1.5rem; 19 | letter-spacing: .4; 20 | display: inline-block; 21 | 22 | &:hover { 23 | color: lighten(#757575, 20%); 24 | padding-left: 19px; 25 | border-left: 1px solid lighten(color("materialize-red", "base"),10%); 26 | } 27 | &.active { 28 | font-weight: 500; 29 | padding-left: 18px; 30 | border-left: 2px solid lighten(color("materialize-red", "base"),10%); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /system/admin/static/editor/sass/components/_tabs.scss: -------------------------------------------------------------------------------- 1 | .tabs { 2 | position: relative; 3 | height: 48px; 4 | background-color: $tabs-bg-color; 5 | margin: 0 auto; 6 | width: 100%; 7 | white-space: nowrap; 8 | 9 | .tab { 10 | display: block; 11 | float: left; 12 | text-align: center; 13 | line-height: 48px; 14 | height: 48px; 15 | padding: 0 20px; 16 | margin: 0; 17 | text-transform: uppercase; 18 | letter-spacing: .8px; 19 | width: 15%; 20 | 21 | a { 22 | color: $tabs-text-color; 23 | display: block; 24 | width: 100%; 25 | height: 100%; 26 | @include transition( color .28s ease); 27 | &:hover { 28 | color: lighten($tabs-text-color, 20%); 29 | } 30 | } 31 | 32 | &.disabled a { 33 | color: lighten($tabs-text-color, 20%); 34 | cursor: default; 35 | } 36 | } 37 | .indicator { 38 | position: absolute; 39 | bottom: 0; 40 | height: 2px; 41 | background-color: $tabs-underline-color; 42 | will-change: left, right; 43 | } 44 | } 45 | 46 | .tabs .tab { padding: 0; } 47 | 48 | -------------------------------------------------------------------------------- /system/admin/static/editor/sass/components/_toast.scss: -------------------------------------------------------------------------------- 1 | #toast-container { 2 | display:block; 3 | position: fixed; 4 | z-index: 1001; 5 | 6 | @media #{$small-and-down} { 7 | min-width: 100%; 8 | bottom: 0%; 9 | } 10 | @media #{$medium-only} { 11 | min-width: 30%; 12 | left: 5%; 13 | bottom: 7%; 14 | } 15 | @media #{$large-and-up} { 16 | min-width: 8%; 17 | top: 10%; 18 | right: 7%; 19 | } 20 | } 21 | 22 | .toast { 23 | @extend .z-depth-1; 24 | border-radius: 2px; 25 | top: 0; 26 | width: auto; 27 | clear: both; 28 | margin-top: 10px; 29 | position: relative; 30 | max-width:100%; 31 | height: $toast-height; 32 | line-height: $toast-height; 33 | background-color: $toast-color; 34 | padding: 0 25px; 35 | font-size: 1.1rem; 36 | font-weight: 300; 37 | color: $toast-text-color; 38 | 39 | @include flexbox(); 40 | @include align(center); 41 | @include justify-content(space-between); 42 | 43 | .btn, .btn-flat { 44 | margin: 0; 45 | margin-left: 3rem; 46 | } 47 | 48 | &.rounded{ 49 | border-radius: 24px; 50 | } 51 | 52 | @media #{$small-and-down} { 53 | width:100%; 54 | border-radius: 0; 55 | } 56 | @media #{$medium-only} { 57 | float: left; 58 | } 59 | @media #{$large-and-up} { 60 | float: right; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /system/admin/static/editor/sass/components/_tooltip.scss: -------------------------------------------------------------------------------- 1 | .material-tooltip { 2 | padding: 10px 8px; 3 | font-size: 1rem; 4 | z-index: 2000; 5 | background-color: transparent; 6 | border-radius: 2px; 7 | color: #fff; 8 | min-height: 36px; 9 | line-height: 1rem; 10 | // max-width: 350px; 11 | opacity: 0; 12 | display: none; 13 | position: absolute; 14 | text-align: center; 15 | overflow: hidden; 16 | left:0; 17 | top:0; 18 | 19 | will-change: top, left; 20 | } 21 | 22 | .backdrop { 23 | position: absolute; 24 | opacity: 0; 25 | display: none; 26 | height: 7px; 27 | width: 14px; 28 | border-radius: 0 0 14px 14px; 29 | background-color: #323232; 30 | z-index: -1; 31 | @include transform-origin( 50% 10%); 32 | 33 | will-change: transform, opacity; 34 | } 35 | -------------------------------------------------------------------------------- /system/admin/static/editor/sass/components/_typography.scss: -------------------------------------------------------------------------------- 1 | a { 2 | text-decoration: none; 3 | } 4 | 5 | html{ 6 | line-height: 1.5; 7 | 8 | @media only screen and (min-width: 0) { 9 | font-size: 14px; 10 | } 11 | 12 | @media only screen and (min-width: $medium-screen) { 13 | font-size: 14.5px; 14 | } 15 | 16 | @media only screen and (min-width: $large-screen) { 17 | font-size: 15px; 18 | } 19 | 20 | font-family: "Roboto", sans-serif; 21 | font-weight: normal; 22 | color: $off-black; 23 | } 24 | h1, h2, h3, h4, h5, h6 { 25 | font-weight: 400; 26 | line-height: 1.1; 27 | } 28 | 29 | // Header Styles 30 | h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { font-weight: inherit; } 31 | h1 { font-size: $h1-fontsize; line-height: 110%; margin: ($h1-fontsize / 2) 0 ($h1-fontsize / 2.5) 0;} 32 | h2 { font-size: $h2-fontsize; line-height: 110%; margin: ($h2-fontsize / 2) 0 ($h2-fontsize / 2.5) 0;} 33 | h3 { font-size: $h3-fontsize; line-height: 110%; margin: ($h3-fontsize / 2) 0 ($h3-fontsize / 2.5) 0;} 34 | h4 { font-size: $h4-fontsize; line-height: 110%; margin: ($h4-fontsize / 2) 0 ($h4-fontsize / 2.5) 0;} 35 | h5 { font-size: $h5-fontsize; line-height: 110%; margin: ($h5-fontsize / 2) 0 ($h5-fontsize / 2.5) 0;} 36 | h6 { font-size: $h6-fontsize; line-height: 110%; margin: ($h6-fontsize / 2) 0 ($h6-fontsize / 2.5) 0;} 37 | 38 | // Text Styles 39 | em { font-style: italic; } 40 | strong { font-weight: 500; } 41 | small { font-size: 75%; } 42 | .light { font-weight: 300; } 43 | .thin { font-weight: 200; } 44 | 45 | .flow-text{ 46 | font-weight: 300; 47 | $i: 0; 48 | @while $i <= $intervals { 49 | @media only screen and (min-width : 360 + ($i * $interval-size)) { 50 | font-size: 1.2rem * (1 + (.02 * $i)); 51 | } 52 | $i: $i + 1; 53 | } 54 | // Handle below 360px screen 55 | @media only screen and (max-width: 360px) { 56 | font-size: 1.2rem; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /system/admin/static/editor/sass/materialize.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | // Mixins 4 | @import "components/prefixer"; 5 | @import "components/mixins"; 6 | @import "components/color"; 7 | 8 | // Variables; 9 | @import "components/variables"; 10 | 11 | // Reset 12 | @import "components/normalize"; 13 | 14 | // components 15 | @import "components/global"; 16 | @import "components/icons-material-design"; 17 | @import "components/grid"; 18 | @import "components/navbar"; 19 | @import "components/roboto"; 20 | @import "components/typography"; 21 | @import "components/cards"; 22 | @import "components/toast"; 23 | @import "components/tabs"; 24 | @import "components/tooltip"; 25 | @import "components/buttons"; 26 | @import "components/dropdown"; 27 | @import "components/waves"; 28 | @import "components/modal"; 29 | @import "components/collapsible"; 30 | @import "components/materialbox"; 31 | @import "components/form"; 32 | @import "components/table_of_contents"; 33 | @import "components/sideNav"; 34 | @import "components/preloader"; 35 | @import "components/slider"; 36 | @import "components/date_picker/default.scss"; 37 | @import "components/date_picker/default.date.scss"; 38 | @import "components/date_picker/default.time.scss"; -------------------------------------------------------------------------------- /system/admin/upload/backup.go: -------------------------------------------------------------------------------- 1 | package upload 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "net/http" 8 | "os" 9 | "path/filepath" 10 | "time" 11 | 12 | "github.com/ponzu-cms/ponzu/system/backup" 13 | ) 14 | 15 | // Backup creates an archive of a project's uploads and writes it 16 | // to the response as a download 17 | func Backup(ctx context.Context, res http.ResponseWriter) error { 18 | ts := time.Now().Unix() 19 | filename := fmt.Sprintf("uploads-%d.bak.tar.gz", ts) 20 | tmp := os.TempDir() 21 | bk := filepath.Join(tmp, filename) 22 | 23 | // create uploads-{stamp}.bak.tar.gz 24 | f, err := os.Create(bk) 25 | if err != nil { 26 | return err 27 | } 28 | 29 | err = backup.ArchiveFS(ctx, "uploads", f) 30 | if err != nil { 31 | return err 32 | } 33 | 34 | err = f.Close() 35 | if err != nil { 36 | return err 37 | } 38 | 39 | // write data to response 40 | data, err := os.Open(bk) 41 | if err != nil { 42 | return err 43 | } 44 | defer data.Close() 45 | defer os.Remove(bk) 46 | 47 | disposition := `attachment; filename=%s` 48 | info, err := data.Stat() 49 | if err != nil { 50 | return err 51 | } 52 | 53 | res.Header().Set("Content-Type", "application/octet-stream") 54 | res.Header().Set("Content-Disposition", fmt.Sprintf(disposition, ts)) 55 | res.Header().Set("Content-Length", fmt.Sprintf("%d", info.Size())) 56 | 57 | _, err = io.Copy(res, data) 58 | 59 | return err 60 | } 61 | -------------------------------------------------------------------------------- /system/api/analytics/backup.go: -------------------------------------------------------------------------------- 1 | package analytics 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "net/http" 7 | "time" 8 | 9 | "github.com/boltdb/bolt" 10 | ) 11 | 12 | // Backup writes a snapshot of the system.db database to an HTTP response. The 13 | // output is discarded if we get a cancellation signal. 14 | func Backup(ctx context.Context, res http.ResponseWriter) error { 15 | errChan := make(chan error, 1) 16 | 17 | go func() { 18 | errChan <- store.View(func(tx *bolt.Tx) error { 19 | ts := time.Now().Unix() 20 | disposition := `attachment; filename="analytics-%d.db.bak"` 21 | 22 | res.Header().Set("Content-Type", "application/octet-stream") 23 | res.Header().Set("Content-Disposition", fmt.Sprintf(disposition, ts)) 24 | res.Header().Set("Content-Length", fmt.Sprintf("%d", int(tx.Size()))) 25 | 26 | _, err := tx.WriteTo(res) 27 | return err 28 | }) 29 | }() 30 | 31 | select { 32 | case <-ctx.Done(): 33 | return ctx.Err() 34 | case err := <-errChan: 35 | return err 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /system/api/analytics/batch.go: -------------------------------------------------------------------------------- 1 | package analytics 2 | 3 | import ( 4 | "encoding/json" 5 | "strconv" 6 | "time" 7 | 8 | "github.com/boltdb/bolt" 9 | ) 10 | 11 | // batchInsert is effectively a specialized version of SetContentMulti from the 12 | // db package, iterating over a []apiRequest instead of []url.Values 13 | func batchInsert(requests chan apiRequest) error { 14 | var reqs []apiRequest 15 | batchSize := len(requestChan) 16 | 17 | for i := 0; i < batchSize; i++ { 18 | reqs = append(reqs, <-requestChan) 19 | } 20 | 21 | err := store.Update(func(tx *bolt.Tx) error { 22 | b, err := tx.CreateBucketIfNotExists([]byte("__requests")) 23 | if err != nil { 24 | return err 25 | } 26 | 27 | for _, apiReq := range reqs { 28 | // get the next available ID and convert to string 29 | // also set effectedID to int of ID 30 | id, err := b.NextSequence() 31 | if err != nil { 32 | return err 33 | } 34 | cid := strconv.FormatUint(id, 10) 35 | 36 | j, err := json.Marshal(apiReq) 37 | if err != nil { 38 | return err 39 | } 40 | 41 | err = b.Put([]byte(cid), j) 42 | if err != nil { 43 | return err 44 | } 45 | } 46 | 47 | return nil 48 | 49 | }) 50 | if err != nil { 51 | return err 52 | } 53 | 54 | return nil 55 | } 56 | 57 | // batchPrune takes a duration to evaluate apiRequest dates against. If any of 58 | // the apiRequest timestamps are before the threshold, they are removed. 59 | // TODO: add feature to alternatively backup old analytics to cloud 60 | func batchPrune(threshold time.Duration) error { 61 | now := time.Now() 62 | today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC) 63 | max := today.Add(threshold) 64 | 65 | // iterate through all request data 66 | err := store.Update(func(tx *bolt.Tx) error { 67 | b := tx.Bucket([]byte("__requests")) 68 | 69 | err := b.ForEach(func(k, v []byte) error { 70 | var r apiRequest 71 | err := json.Unmarshal(v, &r) 72 | if err != nil { 73 | return err 74 | } 75 | 76 | // delete if timestamp is below or equal to max 77 | ts := time.Unix(r.Timestamp/1000, 0) 78 | if ts.Equal(max) || ts.Before(max) { 79 | err := b.Delete(k) 80 | if err != nil { 81 | return err 82 | } 83 | } 84 | 85 | return nil 86 | }) 87 | if err != nil { 88 | return err 89 | } 90 | 91 | return nil 92 | }) 93 | if err != nil { 94 | return err 95 | } 96 | 97 | return nil 98 | } 99 | -------------------------------------------------------------------------------- /system/api/cors.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "net/url" 7 | 8 | "github.com/ponzu-cms/ponzu/system/db" 9 | ) 10 | 11 | // sendPreflight is used to respond to a cross-origin "OPTIONS" request 12 | func sendPreflight(res http.ResponseWriter) { 13 | res.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type") 14 | res.Header().Set("Access-Control-Allow-Origin", "*") 15 | res.WriteHeader(200) 16 | return 17 | } 18 | 19 | func responseWithCORS(res http.ResponseWriter, req *http.Request) (http.ResponseWriter, bool) { 20 | if db.ConfigCache("cors_disabled").(bool) == true { 21 | // check origin matches config domain 22 | domain := db.ConfigCache("domain").(string) 23 | origin := req.Header.Get("Origin") 24 | u, err := url.Parse(origin) 25 | if err != nil { 26 | log.Println("Error parsing URL from request Origin header:", origin) 27 | return res, false 28 | } 29 | 30 | // hack to get dev environments to bypass cors since u.Host (below) will 31 | // be empty, based on Go's url.Parse function 32 | if domain == "localhost" { 33 | domain = "" 34 | } 35 | origin = u.Host 36 | 37 | // currently, this will check for exact match. will need feedback to 38 | // determine if subdomains should be allowed or allow multiple domains 39 | // in config 40 | if origin == domain { 41 | // apply limited CORS headers and return 42 | res.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type") 43 | res.Header().Set("Access-Control-Allow-Origin", domain) 44 | return res, true 45 | } 46 | 47 | // disallow request 48 | res.WriteHeader(http.StatusForbidden) 49 | return res, false 50 | } 51 | 52 | // apply full CORS headers and return 53 | res.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type") 54 | res.Header().Set("Access-Control-Allow-Origin", "*") 55 | 56 | return res, true 57 | } 58 | 59 | // CORS wraps a HandlerFunc to respond to OPTIONS requests properly 60 | func CORS(next http.HandlerFunc) http.HandlerFunc { 61 | return db.CacheControl(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 62 | res, cors := responseWithCORS(res, req) 63 | if !cors { 64 | return 65 | } 66 | 67 | if req.Method == http.MethodOptions { 68 | sendPreflight(res) 69 | return 70 | } 71 | 72 | next.ServeHTTP(res, req) 73 | })) 74 | } 75 | -------------------------------------------------------------------------------- /system/api/gzip.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "compress/gzip" 5 | "net/http" 6 | "strings" 7 | 8 | "github.com/ponzu-cms/ponzu/system/db" 9 | ) 10 | 11 | // Gzip wraps a HandlerFunc to compress responses when possible 12 | func Gzip(next http.HandlerFunc) http.HandlerFunc { 13 | return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 14 | if db.ConfigCache("gzip_disabled").(bool) == true { 15 | next.ServeHTTP(res, req) 16 | return 17 | } 18 | 19 | // check if req header content-encoding supports gzip 20 | if strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") { 21 | // gzip response data 22 | res.Header().Set("Content-Encoding", "gzip") 23 | gzWriter := gzip.NewWriter(res) 24 | defer gzWriter.Close() 25 | var gzres gzipResponseWriter 26 | if pusher, ok := res.(http.Pusher); ok { 27 | gzres = gzipResponseWriter{res, pusher, gzWriter} 28 | } else { 29 | gzres = gzipResponseWriter{res, nil, gzWriter} 30 | } 31 | 32 | next.ServeHTTP(gzres, req) 33 | return 34 | } 35 | 36 | next.ServeHTTP(res, req) 37 | }) 38 | } 39 | 40 | type gzipResponseWriter struct { 41 | http.ResponseWriter 42 | pusher http.Pusher 43 | 44 | gw *gzip.Writer 45 | } 46 | 47 | func (gzw gzipResponseWriter) Write(p []byte) (int, error) { 48 | return gzw.gw.Write(p) 49 | } 50 | 51 | func (gzw gzipResponseWriter) Push(target string, opts *http.PushOptions) error { 52 | if gzw.pusher == nil { 53 | return nil 54 | } 55 | 56 | if opts == nil { 57 | opts = &http.PushOptions{ 58 | Header: make(http.Header), 59 | } 60 | } 61 | 62 | opts.Header.Set("Accept-Encoding", "gzip") 63 | 64 | return gzw.pusher.Push(target, opts) 65 | } 66 | -------------------------------------------------------------------------------- /system/api/hide.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/ponzu-cms/ponzu/system/item" 7 | ) 8 | 9 | func hide(res http.ResponseWriter, req *http.Request, it interface{}) bool { 10 | // check if should be hidden 11 | if h, ok := it.(item.Hideable); ok { 12 | err := h.Hide(res, req) 13 | if err == item.ErrAllowHiddenItem { 14 | return false 15 | } 16 | 17 | if err != nil { 18 | res.WriteHeader(http.StatusInternalServerError) 19 | return true 20 | } 21 | 22 | res.WriteHeader(http.StatusNotFound) 23 | return true 24 | } 25 | 26 | return false 27 | } 28 | -------------------------------------------------------------------------------- /system/api/json.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "log" 7 | "net/http" 8 | ) 9 | 10 | func fmtJSON(data ...json.RawMessage) ([]byte, error) { 11 | var msg = []json.RawMessage{} 12 | for _, d := range data { 13 | msg = append(msg, d) 14 | } 15 | 16 | resp := map[string][]json.RawMessage{ 17 | "data": msg, 18 | } 19 | 20 | var buf = &bytes.Buffer{} 21 | enc := json.NewEncoder(buf) 22 | err := enc.Encode(resp) 23 | if err != nil { 24 | log.Println("Failed to encode data to JSON:", err) 25 | return nil, err 26 | } 27 | 28 | return buf.Bytes(), nil 29 | } 30 | 31 | func toJSON(data []string) ([]byte, error) { 32 | var buf = &bytes.Buffer{} 33 | enc := json.NewEncoder(buf) 34 | resp := map[string][]string{ 35 | "data": data, 36 | } 37 | 38 | err := enc.Encode(resp) 39 | if err != nil { 40 | log.Println("Failed to encode data to JSON:", err) 41 | return nil, err 42 | } 43 | 44 | return buf.Bytes(), nil 45 | } 46 | 47 | // sendData should be used any time you want to communicate 48 | // data back to a foreign client 49 | func sendData(res http.ResponseWriter, req *http.Request, data []byte) { 50 | res.Header().Set("Content-Type", "application/json") 51 | res.Header().Set("Vary", "Accept-Encoding") 52 | 53 | _, err := res.Write(data) 54 | if err != nil { 55 | log.Println("Error writing to response in sendData") 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /system/api/omit.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | 8 | "github.com/ponzu-cms/ponzu/system/item" 9 | 10 | "github.com/tidwall/gjson" 11 | "github.com/tidwall/sjson" 12 | ) 13 | 14 | func omit(res http.ResponseWriter, req *http.Request, it interface{}, data []byte) ([]byte, error) { 15 | // is it Omittable 16 | om, ok := it.(item.Omittable) 17 | if !ok { 18 | return data, nil 19 | } 20 | 21 | return omitFields(res, req, om, data, "data") 22 | } 23 | 24 | func omitFields(res http.ResponseWriter, req *http.Request, om item.Omittable, data []byte, pathPrefix string) ([]byte, error) { 25 | // get fields to omit from json data 26 | fields, err := om.Omit(res, req) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | // remove each field from json, all responses contain json object(s) in top-level "data" array 32 | n := int(gjson.GetBytes(data, pathPrefix+".#").Int()) 33 | for i := 0; i < n; i++ { 34 | for k := range fields { 35 | var err error 36 | data, err = sjson.DeleteBytes(data, fmt.Sprintf("%s.%d.%s", pathPrefix, i, fields[k])) 37 | if err != nil { 38 | log.Println("Erorr omitting field:", fields[k], "from item.Omittable:", om) 39 | return nil, err 40 | } 41 | } 42 | } 43 | 44 | return data, nil 45 | } 46 | -------------------------------------------------------------------------------- /system/api/push.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "strings" 7 | 8 | "github.com/ponzu-cms/ponzu/system/item" 9 | 10 | "github.com/tidwall/gjson" 11 | ) 12 | 13 | const errRecursivePush = "recursive push not allowed" 14 | 15 | func push(res http.ResponseWriter, req *http.Request, pt interface{}, data []byte) { 16 | // Push(target string, opts *PushOptions) error 17 | if pusher, ok := res.(http.Pusher); ok { 18 | if p, ok := pt.(item.Pushable); ok { 19 | // get fields to pull values from data 20 | fields, err := p.Push(res, req) 21 | if err != nil { 22 | log.Println("[Pushable] error:", err) 23 | return 24 | } 25 | 26 | // parse values from data to push 27 | values := gjson.GetManyBytes(data, fields...) 28 | 29 | // push all values from Pushable items' fields 30 | for i := range values { 31 | val := values[i] 32 | val.ForEach(func(k, v gjson.Result) bool { 33 | if v.String() == "null" { 34 | return true 35 | } 36 | 37 | // check that the push is not to its parent URL 38 | if v.String() == (req.URL.Path + "?" + req.URL.RawQuery) { 39 | return true 40 | } 41 | 42 | err := pusher.Push(v.String(), nil) 43 | // check for error, "http2: recursive push not allowed" 44 | // and return, suppressing a log message 45 | // XXX: errRecursivePush has been co-located to this 46 | // package instead of importing golang.org/x/net/http2 47 | // to get the error itself. 48 | if err != nil && strings.Contains(err.Error(), errRecursivePush) { 49 | return true 50 | } 51 | if err != nil { 52 | log.Println("Error during Push of value:", v.String(), err) 53 | } 54 | 55 | return true 56 | }) 57 | } 58 | } 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /system/api/record.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/ponzu-cms/ponzu/system/api/analytics" 7 | ) 8 | 9 | // Record wraps a HandlerFunc to record API requests for analytical purposes 10 | func Record(next http.HandlerFunc) http.HandlerFunc { 11 | return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 12 | go analytics.Record(req) 13 | 14 | next.ServeHTTP(res, req) 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /system/api/server.go: -------------------------------------------------------------------------------- 1 | // Package api sets the various API handlers which provide an HTTP interface to 2 | // Ponzu content, and include the types and interfaces to enable client-side 3 | // interactivity with the system. 4 | package api 5 | 6 | import "net/http" 7 | 8 | // Run adds Handlers to default http listener for API 9 | func Run() { 10 | http.HandleFunc("/api/contents", Record(CORS(Gzip(contentsHandler)))) 11 | 12 | http.HandleFunc("/api/content", Record(CORS(Gzip(contentHandler)))) 13 | 14 | http.HandleFunc("/api/content/create", Record(CORS(createContentHandler))) 15 | 16 | http.HandleFunc("/api/content/update", Record(CORS(updateContentHandler))) 17 | 18 | http.HandleFunc("/api/content/delete", Record(CORS(deleteContentHandler))) 19 | 20 | http.HandleFunc("/api/search", Record(CORS(Gzip(searchContentHandler)))) 21 | 22 | http.HandleFunc("/api/uploads", Record(CORS(Gzip(uploadsHandler)))) 23 | } 24 | -------------------------------------------------------------------------------- /system/backup/archive.go: -------------------------------------------------------------------------------- 1 | package backup 2 | 3 | import ( 4 | "archive/tar" 5 | "compress/gzip" 6 | "context" 7 | "fmt" 8 | "io" 9 | "os" 10 | "path/filepath" 11 | ) 12 | 13 | // ArchiveFS walks the filesystem starting from basedir writing files encountered 14 | // tarred and gzipped to the provided writer 15 | func ArchiveFS(ctx context.Context, basedir string, w io.Writer) error { 16 | gz := gzip.NewWriter(w) 17 | tarball := tar.NewWriter(gz) 18 | 19 | absPath, err := filepath.Abs(basedir) 20 | if err != nil { 21 | return err 22 | } 23 | 24 | info, err := os.Lstat(absPath) 25 | if err != nil { 26 | return err 27 | } 28 | 29 | if info.Mode()&os.ModeSymlink == os.ModeSymlink { 30 | // This is a symlink - we need to follow it 31 | bdir, err := os.Readlink(absPath) 32 | if err != nil { 33 | return err 34 | } 35 | basedir = bdir 36 | } 37 | 38 | errChan := make(chan error, 1) 39 | walkFn := func(path string, info os.FileInfo, err error) error { 40 | if err != nil { 41 | return err 42 | } 43 | 44 | hdr, err := tar.FileInfoHeader(info, "") 45 | if err != nil { 46 | return err 47 | } 48 | 49 | hdr.Name = path 50 | 51 | err = tarball.WriteHeader(hdr) 52 | if err != nil { 53 | return err 54 | } 55 | 56 | if !info.IsDir() { 57 | src, err := os.Open(path) 58 | if err != nil { 59 | return err 60 | } 61 | defer src.Close() 62 | 63 | _, err = io.Copy(tarball, src) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | err = tarball.Flush() 69 | if err != nil { 70 | return err 71 | } 72 | 73 | err = gz.Flush() 74 | if err != nil { 75 | return err 76 | } 77 | } 78 | 79 | return nil 80 | } 81 | 82 | // stop processing if we get a cancellation signal 83 | err = filepath.Walk(basedir, func(path string, info os.FileInfo, err error) error { 84 | go func() { errChan <- walkFn(path, info, err) }() 85 | 86 | select { 87 | case <-ctx.Done(): 88 | if err := ctx.Err(); err != nil { 89 | return err 90 | } 91 | case err := <-errChan: 92 | if err != nil { 93 | return err 94 | } 95 | } 96 | 97 | return nil 98 | }) 99 | if err != nil { 100 | fmt.Println(err) 101 | return err 102 | } 103 | 104 | err = gz.Close() 105 | if err != nil { 106 | return err 107 | } 108 | err = tarball.Close() 109 | if err != nil { 110 | return err 111 | } 112 | 113 | return nil 114 | } 115 | -------------------------------------------------------------------------------- /system/cfg/env.go: -------------------------------------------------------------------------------- 1 | package cfg 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "path/filepath" 7 | ) 8 | 9 | func getWd() string { 10 | wd, err := os.Getwd() 11 | if err != nil { 12 | log.Fatalln("Couldn't find working directory", err) 13 | } 14 | return wd 15 | } 16 | 17 | func DataDir() string { 18 | dataDir := os.Getenv("PONZU_DATA_DIR") 19 | if dataDir == "" { 20 | return getWd() 21 | } 22 | return dataDir 23 | } 24 | 25 | func TlsDir() string { 26 | tlsDir := os.Getenv("PONZU_TLS_DIR") 27 | if tlsDir == "" { 28 | tlsDir = filepath.Join(getWd(), "cmd", "ponzu", "vendor", "github.com", "ponzu-cms", "ponzu", "system", "tls") 29 | } 30 | return tlsDir 31 | } 32 | 33 | func AdminStaticDir() string { 34 | staticDir := os.Getenv("PONZU_ADMINSTATIC_DIR") 35 | if staticDir == "" { 36 | 37 | staticDir = filepath.Join(getWd(), "cmd", "ponzu", "vendor", "github.com", "ponzu-cms", "ponzu", "system", "admin", "static") 38 | } 39 | return staticDir 40 | } 41 | 42 | func UploadDir() string { 43 | uploadDir := os.Getenv("PONZU_UPLOAD_DIR") 44 | if uploadDir == "" { 45 | uploadDir = filepath.Join(DataDir(),"uploads") 46 | } 47 | return uploadDir 48 | } 49 | 50 | func SearchDir() string { 51 | searchDir := os.Getenv("PONZU_SEARCH_DIR") 52 | if searchDir == "" { 53 | searchDir = filepath.Join(DataDir(),"search") 54 | } 55 | return searchDir 56 | } 57 | -------------------------------------------------------------------------------- /system/db/backup.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "net/http" 7 | "time" 8 | 9 | "github.com/boltdb/bolt" 10 | ) 11 | 12 | // Backup writes a snapshot of the system.db database to an HTTP response. The 13 | // output is discarded if we get a cancellation signal. 14 | func Backup(ctx context.Context, res http.ResponseWriter) error { 15 | errChan := make(chan error, 1) 16 | 17 | go func() { 18 | errChan <- store.View(func(tx *bolt.Tx) error { 19 | ts := time.Now().Unix() 20 | disposition := `attachment; filename="system-%d.db.bak"` 21 | 22 | res.Header().Set("Content-Type", "application/octet-stream") 23 | res.Header().Set("Content-Disposition", fmt.Sprintf(disposition, ts)) 24 | res.Header().Set("Content-Length", fmt.Sprintf("%d", int(tx.Size()))) 25 | 26 | _, err := tx.WriteTo(res) 27 | return err 28 | }) 29 | }() 30 | 31 | select { 32 | case <-ctx.Done(): 33 | return ctx.Err() 34 | case err := <-errChan: 35 | return err 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /system/db/cache.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "encoding/base64" 5 | "fmt" 6 | "net/http" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | // CacheControl sets the default cache policy on static asset responses 12 | func CacheControl(next http.Handler) http.HandlerFunc { 13 | return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 14 | cacheDisabled := ConfigCache("cache_disabled").(bool) 15 | if cacheDisabled { 16 | res.Header().Add("Cache-Control", "no-cache") 17 | next.ServeHTTP(res, req) 18 | } else { 19 | age := int64(ConfigCache("cache_max_age").(float64)) 20 | etag := ConfigCache("etag").(string) 21 | if age == 0 { 22 | age = DefaultMaxAge 23 | } 24 | policy := fmt.Sprintf("max-age=%d, public", age) 25 | res.Header().Add("ETag", etag) 26 | res.Header().Add("Cache-Control", policy) 27 | 28 | if match := req.Header.Get("If-None-Match"); match != "" { 29 | if strings.Contains(match, etag) { 30 | res.WriteHeader(http.StatusNotModified) 31 | return 32 | } 33 | } 34 | 35 | next.ServeHTTP(res, req) 36 | } 37 | }) 38 | } 39 | 40 | // NewEtag generates a new Etag for response caching 41 | func NewEtag() string { 42 | now := fmt.Sprintf("%d", time.Now().Unix()) 43 | etag := base64.StdEncoding.EncodeToString([]byte(now)) 44 | 45 | return etag 46 | } 47 | 48 | // InvalidateCache sets a new Etag for http responses 49 | func InvalidateCache() error { 50 | err := PutConfig("etag", NewEtag()) 51 | if err != nil { 52 | return err 53 | } 54 | 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /system/db/index.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | 7 | "github.com/boltdb/bolt" 8 | ) 9 | 10 | // Index gets the value from the namespace at the key provided 11 | func Index(namespace, key string) ([]byte, error) { 12 | val := &bytes.Buffer{} 13 | err := store.View(func(tx *bolt.Tx) error { 14 | b := tx.Bucket([]byte(index(namespace))) 15 | if b == nil { 16 | return nil 17 | } 18 | 19 | v := b.Get([]byte(key)) 20 | 21 | _, err := val.Write(v) 22 | if err != nil { 23 | return err 24 | } 25 | 26 | return nil 27 | }) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | return val.Bytes(), nil 33 | } 34 | 35 | // SetIndex sets a key/value pair within the namespace provided and will return 36 | // an error if it fails 37 | func SetIndex(namespace, key string, value interface{}) error { 38 | return store.Update(func(tx *bolt.Tx) error { 39 | b, err := tx.CreateBucketIfNotExists([]byte(index(namespace))) 40 | if err != nil { 41 | return err 42 | } 43 | 44 | val, err := json.Marshal(value) 45 | if err != nil { 46 | return err 47 | } 48 | 49 | return b.Put([]byte(key), val) 50 | }) 51 | } 52 | 53 | // DeleteIndex removes the key and value from the namespace provided and will 54 | // return an error if it fails. It will return nil if there was no key/value in 55 | // the index to delete. 56 | func DeleteIndex(namespace, key string) error { 57 | return store.Update(func(tx *bolt.Tx) error { 58 | b := tx.Bucket([]byte(index(namespace))) 59 | if b == nil { 60 | return nil 61 | } 62 | 63 | return b.Delete([]byte(key)) 64 | }) 65 | } 66 | 67 | // DropIndex removes the index and all key/value pairs in the namespace index 68 | func DropIndex(namespace string) error { 69 | return store.Update(func(tx *bolt.Tx) error { 70 | err := tx.DeleteBucket([]byte(index(namespace))) 71 | if err == bolt.ErrBucketNotFound { 72 | return nil 73 | } 74 | 75 | if err != nil { 76 | return err 77 | } 78 | 79 | return nil 80 | }) 81 | } 82 | 83 | func index(namespace string) string { 84 | return "__index_" + namespace 85 | } 86 | -------------------------------------------------------------------------------- /system/item/types.go: -------------------------------------------------------------------------------- 1 | package item 2 | 3 | import "errors" 4 | 5 | const ( 6 | typeNotRegistered = `Error: 7 | There is no type registered for %[1]s 8 | 9 | Add this to the file which defines %[1]s{} in the 'content' package: 10 | 11 | 12 | func init() { 13 | item.Types["%[1]s"] = func() interface{} { return new(%[1]s) } 14 | } 15 | 16 | 17 | ` 18 | ) 19 | 20 | var ( 21 | // ErrTypeNotRegistered means content type isn't registered (not found in Types map) 22 | ErrTypeNotRegistered = errors.New(typeNotRegistered) 23 | 24 | // ErrAllowHiddenItem should be used as an error to tell a caller of Hideable#Hide 25 | // that this type is hidden, but should be shown in a particular case, i.e. 26 | // if requested by a valid admin or user 27 | ErrAllowHiddenItem = errors.New(`Allow hidden item`) 28 | 29 | // Types is a map used to reference a type name to its actual Editable type 30 | // mainly for lookups in /admin route based utilities 31 | Types map[string]func() interface{} 32 | ) 33 | 34 | func init() { 35 | Types = make(map[string]func() interface{}) 36 | } 37 | -------------------------------------------------------------------------------- /system/search/backup.go: -------------------------------------------------------------------------------- 1 | package search 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "net/http" 8 | "os" 9 | "path/filepath" 10 | "time" 11 | 12 | "github.com/ponzu-cms/ponzu/system/cfg" 13 | 14 | "github.com/ponzu-cms/ponzu/system/backup" 15 | ) 16 | 17 | // Backup creates an archive of a project's search index and writes it 18 | // to the response as a download 19 | func Backup(ctx context.Context, res http.ResponseWriter) error { 20 | ts := time.Now().Unix() 21 | filename := fmt.Sprintf("search-%d.bak.tar.gz", ts) 22 | tmp := os.TempDir() 23 | bk := filepath.Join(tmp, filename) 24 | 25 | // create search-{stamp}.bak.tar.gz 26 | f, err := os.Create(bk) 27 | if err != nil { 28 | return err 29 | } 30 | 31 | err = backup.ArchiveFS(ctx, cfg.SearchDir(), f) 32 | if err != nil { 33 | return err 34 | } 35 | 36 | err = f.Close() 37 | if err != nil { 38 | return err 39 | } 40 | 41 | // write data to response 42 | data, err := os.Open(bk) 43 | if err != nil { 44 | return err 45 | } 46 | defer data.Close() 47 | defer os.Remove(bk) 48 | 49 | disposition := `attachment; filename=%s` 50 | info, err := data.Stat() 51 | if err != nil { 52 | return err 53 | } 54 | 55 | res.Header().Set("Content-Type", "application/octet-stream") 56 | res.Header().Set("Content-Disposition", fmt.Sprintf(disposition, ts)) 57 | res.Header().Set("Content-Length", fmt.Sprintf("%d", info.Size())) 58 | 59 | _, err = io.Copy(res, data) 60 | 61 | return err 62 | } 63 | -------------------------------------------------------------------------------- /system/system.go: -------------------------------------------------------------------------------- 1 | // Package system contains a collection of packages that make up the internal 2 | // Ponzu system, which handles addons, administration, the Admin server, the API 3 | // server, analytics, databases, search, TLS, and various internal types. 4 | package system 5 | 6 | import ( 7 | "net/http" 8 | 9 | "github.com/ponzu-cms/ponzu/system/db" 10 | ) 11 | 12 | // BasicAuth adds HTTP Basic Auth check for requests that should implement it 13 | func BasicAuth(next http.HandlerFunc) http.HandlerFunc { 14 | return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 15 | u := db.ConfigCache("backup_basic_auth_user").(string) 16 | p := db.ConfigCache("backup_basic_auth_password").(string) 17 | 18 | if u == "" || p == "" { 19 | res.WriteHeader(http.StatusForbidden) 20 | return 21 | } 22 | 23 | user, password, ok := req.BasicAuth() 24 | 25 | if !ok { 26 | res.WriteHeader(http.StatusForbidden) 27 | return 28 | } 29 | 30 | if u != user || p != password { 31 | res.WriteHeader(http.StatusUnauthorized) 32 | return 33 | } 34 | 35 | next.ServeHTTP(res, req) 36 | }) 37 | } 38 | -------------------------------------------------------------------------------- /system/tls/enabledev.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "path/filepath" 7 | 8 | "github.com/ponzu-cms/ponzu/system/cfg" 9 | ) 10 | 11 | // EnableDev generates self-signed SSL certificates to use HTTPS & HTTP/2 while 12 | // working in a development environment. The certs are saved in a different 13 | // directory than the production certs (from Let's Encrypt), so that the 14 | // acme/autocert package doesn't mistake them for it's own. 15 | // Additionally, a TLS server is started using the default http mux. 16 | func EnableDev() { 17 | setupDev() 18 | 19 | vendorPath := cfg.TlsDir() 20 | cert := filepath.Join(vendorPath, "devcerts", "cert.pem") 21 | key := filepath.Join(vendorPath, "devcerts", "key.pem") 22 | 23 | log.Fatalln(http.ListenAndServeTLS(":10443", cert, key, nil)) 24 | } 25 | --------------------------------------------------------------------------------