├── .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 | [](https://godoc.org/github.com/gorilla/schema) [](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 |
2 |
3 | {{summary}}
4 |
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 | 
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 |
--------------------------------------------------------------------------------