├── .github ├── FUNDING.yml └── workflows │ └── test.yml ├── .gitignore ├── LICENSE ├── README.md ├── project.clj ├── resources ├── html │ ├── simple.html │ └── with-param.html └── markdown │ ├── simple.md │ └── with-param.md ├── src └── tadam │ ├── core.clj │ ├── db.clj │ ├── email.clj │ ├── forms.clj │ ├── responses.clj │ ├── sessions.clj │ ├── templates.clj │ └── utils.clj └── test └── tadam ├── core_test.clj └── templates_test.clj /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: tanrax 2 | patreon: androsfenollosa 3 | ko_fi: androsfenollosa 4 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v1 12 | - name: Install dependencies 13 | run: lein deps 14 | - name: Testing 15 | run: lein test 16 | - name: Run check format 17 | run: lein check-format 18 | - name: Run check idiomatic 19 | run: lein check-idiomatic 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | */**/.DS_Store 2 | .DS_Store 3 | 4 | .lein-failures 5 | .lein-repl-history 6 | target/ 7 | 8 | pom.xml -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Eclipse Public License - v 2.0 2 | 3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE 4 | PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION 5 | OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 6 | 7 | 1. DEFINITIONS 8 | 9 | "Contribution" means: 10 | 11 | a) in the case of the initial Contributor, the initial content 12 | Distributed under this Agreement, and 13 | 14 | b) in the case of each subsequent Contributor: 15 | i) changes to the Program, and 16 | ii) additions to the Program; 17 | where such changes and/or additions to the Program originate from 18 | and are Distributed by that particular Contributor. A Contribution 19 | "originates" from a Contributor if it was added to the Program by 20 | such Contributor itself or anyone acting on such Contributor's behalf. 21 | Contributions do not include changes or additions to the Program that 22 | are not Modified Works. 23 | 24 | "Contributor" means any person or entity that Distributes the Program. 25 | 26 | "Licensed Patents" mean patent claims licensable by a Contributor which 27 | are necessarily infringed by the use or sale of its Contribution alone 28 | or when combined with the Program. 29 | 30 | "Program" means the Contributions Distributed in accordance with this 31 | Agreement. 32 | 33 | "Recipient" means anyone who receives the Program under this Agreement 34 | or any Secondary License (as applicable), including Contributors. 35 | 36 | "Derivative Works" shall mean any work, whether in Source Code or other 37 | form, that is based on (or derived from) the Program and for which the 38 | editorial revisions, annotations, elaborations, or other modifications 39 | represent, as a whole, an original work of authorship. 40 | 41 | "Modified Works" shall mean any work in Source Code or other form that 42 | results from an addition to, deletion from, or modification of the 43 | contents of the Program, including, for purposes of clarity any new file 44 | in Source Code form that contains any contents of the Program. Modified 45 | Works shall not include works that contain only declarations, 46 | interfaces, types, classes, structures, or files of the Program solely 47 | in each case in order to link to, bind by name, or subclass the Program 48 | or Modified Works thereof. 49 | 50 | "Distribute" means the acts of a) distributing or b) making available 51 | in any manner that enables the transfer of a copy. 52 | 53 | "Source Code" means the form of a Program preferred for making 54 | modifications, including but not limited to software source code, 55 | documentation source, and configuration files. 56 | 57 | "Secondary License" means either the GNU General Public License, 58 | Version 2.0, or any later versions of that license, including any 59 | exceptions or additional permissions as identified by the initial 60 | Contributor. 61 | 62 | 2. GRANT OF RIGHTS 63 | 64 | a) Subject to the terms of this Agreement, each Contributor hereby 65 | grants Recipient a non-exclusive, worldwide, royalty-free copyright 66 | license to reproduce, prepare Derivative Works of, publicly display, 67 | publicly perform, Distribute and sublicense the Contribution of such 68 | Contributor, if any, and such Derivative Works. 69 | 70 | b) Subject to the terms of this Agreement, each Contributor hereby 71 | grants Recipient a non-exclusive, worldwide, royalty-free patent 72 | license under Licensed Patents to make, use, sell, offer to sell, 73 | import and otherwise transfer the Contribution of such Contributor, 74 | if any, in Source Code or other form. This patent license shall 75 | apply to the combination of the Contribution and the Program if, at 76 | the time the Contribution is added by the Contributor, such addition 77 | of the Contribution causes such combination to be covered by the 78 | Licensed Patents. The patent license shall not apply to any other 79 | combinations which include the Contribution. No hardware per se is 80 | licensed hereunder. 81 | 82 | c) Recipient understands that although each Contributor grants the 83 | licenses to its Contributions set forth herein, no assurances are 84 | provided by any Contributor that the Program does not infringe the 85 | patent or other intellectual property rights of any other entity. 86 | Each Contributor disclaims any liability to Recipient for claims 87 | brought by any other entity based on infringement of intellectual 88 | property rights or otherwise. As a condition to exercising the 89 | rights and licenses granted hereunder, each Recipient hereby 90 | assumes sole responsibility to secure any other intellectual 91 | property rights needed, if any. For example, if a third party 92 | patent license is required to allow Recipient to Distribute the 93 | Program, it is Recipient's responsibility to acquire that license 94 | before distributing the Program. 95 | 96 | d) Each Contributor represents that to its knowledge it has 97 | sufficient copyright rights in its Contribution, if any, to grant 98 | the copyright license set forth in this Agreement. 99 | 100 | e) Notwithstanding the terms of any Secondary License, no 101 | Contributor makes additional grants to any Recipient (other than 102 | those set forth in this Agreement) as a result of such Recipient's 103 | receipt of the Program under the terms of a Secondary License 104 | (if permitted under the terms of Section 3). 105 | 106 | 3. REQUIREMENTS 107 | 108 | 3.1 If a Contributor Distributes the Program in any form, then: 109 | 110 | a) the Program must also be made available as Source Code, in 111 | accordance with section 3.2, and the Contributor must accompany 112 | the Program with a statement that the Source Code for the Program 113 | is available under this Agreement, and informs Recipients how to 114 | obtain it in a reasonable manner on or through a medium customarily 115 | used for software exchange; and 116 | 117 | b) the Contributor may Distribute the Program under a license 118 | different than this Agreement, provided that such license: 119 | i) effectively disclaims on behalf of all other Contributors all 120 | warranties and conditions, express and implied, including 121 | warranties or conditions of title and non-infringement, and 122 | implied warranties or conditions of merchantability and fitness 123 | for a particular purpose; 124 | 125 | ii) effectively excludes on behalf of all other Contributors all 126 | liability for damages, including direct, indirect, special, 127 | incidental and consequential damages, such as lost profits; 128 | 129 | iii) does not attempt to limit or alter the recipients' rights 130 | in the Source Code under section 3.2; and 131 | 132 | iv) requires any subsequent distribution of the Program by any 133 | party to be under a license that satisfies the requirements 134 | of this section 3. 135 | 136 | 3.2 When the Program is Distributed as Source Code: 137 | 138 | a) it must be made available under this Agreement, or if the 139 | Program (i) is combined with other material in a separate file or 140 | files made available under a Secondary License, and (ii) the initial 141 | Contributor attached to the Source Code the notice described in 142 | Exhibit A of this Agreement, then the Program may be made available 143 | under the terms of such Secondary Licenses, and 144 | 145 | b) a copy of this Agreement must be included with each copy of 146 | the Program. 147 | 148 | 3.3 Contributors may not remove or alter any copyright, patent, 149 | trademark, attribution notices, disclaimers of warranty, or limitations 150 | of liability ("notices") contained within the Program from any copy of 151 | the Program which they Distribute, provided that Contributors may add 152 | their own appropriate notices. 153 | 154 | 4. COMMERCIAL DISTRIBUTION 155 | 156 | Commercial distributors of software may accept certain responsibilities 157 | with respect to end users, business partners and the like. While this 158 | license is intended to facilitate the commercial use of the Program, 159 | the Contributor who includes the Program in a commercial product 160 | offering should do so in a manner which does not create potential 161 | liability for other Contributors. Therefore, if a Contributor includes 162 | the Program in a commercial product offering, such Contributor 163 | ("Commercial Contributor") hereby agrees to defend and indemnify every 164 | other Contributor ("Indemnified Contributor") against any losses, 165 | damages and costs (collectively "Losses") arising from claims, lawsuits 166 | and other legal actions brought by a third party against the Indemnified 167 | Contributor to the extent caused by the acts or omissions of such 168 | Commercial Contributor in connection with its distribution of the Program 169 | in a commercial product offering. The obligations in this section do not 170 | apply to any claims or Losses relating to any actual or alleged 171 | intellectual property infringement. In order to qualify, an Indemnified 172 | Contributor must: a) promptly notify the Commercial Contributor in 173 | writing of such claim, and b) allow the Commercial Contributor to control, 174 | and cooperate with the Commercial Contributor in, the defense and any 175 | related settlement negotiations. The Indemnified Contributor may 176 | participate in any such claim at its own expense. 177 | 178 | For example, a Contributor might include the Program in a commercial 179 | product offering, Product X. That Contributor is then a Commercial 180 | Contributor. If that Commercial Contributor then makes performance 181 | claims, or offers warranties related to Product X, those performance 182 | claims and warranties are such Commercial Contributor's responsibility 183 | alone. Under this section, the Commercial Contributor would have to 184 | defend claims against the other Contributors related to those performance 185 | claims and warranties, and if a court requires any other Contributor to 186 | pay any damages as a result, the Commercial Contributor must pay 187 | those damages. 188 | 189 | 5. NO WARRANTY 190 | 191 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT 192 | PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" 193 | BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 194 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF 195 | TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR 196 | PURPOSE. Each Recipient is solely responsible for determining the 197 | appropriateness of using and distributing the Program and assumes all 198 | risks associated with its exercise of rights under this Agreement, 199 | including but not limited to the risks and costs of program errors, 200 | compliance with applicable laws, damage to or loss of data, programs 201 | or equipment, and unavailability or interruption of operations. 202 | 203 | 6. DISCLAIMER OF LIABILITY 204 | 205 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT 206 | PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS 207 | SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 208 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST 209 | PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 210 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 211 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 212 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE 213 | POSSIBILITY OF SUCH DAMAGES. 214 | 215 | 7. GENERAL 216 | 217 | If any provision of this Agreement is invalid or unenforceable under 218 | applicable law, it shall not affect the validity or enforceability of 219 | the remainder of the terms of this Agreement, and without further 220 | action by the parties hereto, such provision shall be reformed to the 221 | minimum extent necessary to make such provision valid and enforceable. 222 | 223 | If Recipient institutes patent litigation against any entity 224 | (including a cross-claim or counterclaim in a lawsuit) alleging that the 225 | Program itself (excluding combinations of the Program with other software 226 | or hardware) infringes such Recipient's patent(s), then such Recipient's 227 | rights granted under Section 2(b) shall terminate as of the date such 228 | litigation is filed. 229 | 230 | All Recipient's rights under this Agreement shall terminate if it 231 | fails to comply with any of the material terms or conditions of this 232 | Agreement and does not cure such failure in a reasonable period of 233 | time after becoming aware of such noncompliance. If all Recipient's 234 | rights under this Agreement terminate, Recipient agrees to cease use 235 | and distribution of the Program as soon as reasonably practicable. 236 | However, Recipient's obligations under this Agreement and any licenses 237 | granted by Recipient relating to the Program shall continue and survive. 238 | 239 | Everyone is permitted to copy and distribute copies of this Agreement, 240 | but in order to avoid inconsistency the Agreement is copyrighted and 241 | may only be modified in the following manner. The Agreement Steward 242 | reserves the right to publish new versions (including revisions) of 243 | this Agreement from time to time. No one other than the Agreement 244 | Steward has the right to modify this Agreement. The Eclipse Foundation 245 | is the initial Agreement Steward. The Eclipse Foundation may assign the 246 | responsibility to serve as the Agreement Steward to a suitable separate 247 | entity. Each new version of the Agreement will be given a distinguishing 248 | version number. The Program (including Contributions) may always be 249 | Distributed subject to the version of the Agreement under which it was 250 | received. In addition, after a new version of the Agreement is published, 251 | Contributor may elect to Distribute the Program (including its 252 | Contributions) under the new version. 253 | 254 | Except as expressly stated in Sections 2(a) and 2(b) above, Recipient 255 | receives no rights or licenses to the intellectual property of any 256 | Contributor under this Agreement, whether expressly, by implication, 257 | estoppel or otherwise. All rights in the Program not expressly granted 258 | under this Agreement are reserved. Nothing in this Agreement is intended 259 | to be enforceable by any entity that is not a Contributor or Recipient. 260 | No third-party beneficiary rights are created under this Agreement. 261 | 262 | Exhibit A - Form of Secondary Licenses Notice 263 | 264 | "This Source Code may also be made available under the following 265 | Secondary Licenses when the conditions for such availability set forth 266 | in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), 267 | version(s), and exceptions or additional permissions here}." 268 | 269 | Simply including a copy of this Agreement, including this Exhibit A 270 | is not sufficient to license the Source Code under Secondary Licenses. 271 | 272 | If it is not possible or desirable to put the notice in a particular 273 | file, then You may include the notice in a location (such as a LICENSE 274 | file in a relevant directory) where a recipient would be likely to 275 | look for such a notice. 276 | 277 | You may add additional accurate notices of copyright ownership. 278 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 |

Tadam Framework

5 |

Core

6 |

7 | 8 |

9 | 10 | ## Dev tools 11 | 12 | It needs to be executed at the root of the project and have `Leiningen` installed. 13 | 14 | ### Lint 15 | 16 | It checks linguistically and syntaxically if the code is correct. 17 | 18 | ``` shell 19 | make lint 20 | ``` 21 | 22 | ### Build 23 | 24 | Build a JAR ready to distribute. 25 | 26 | ``` shell 27 | make build 28 | ``` 29 | 30 | ### Deploy 31 | 32 | Distributed in Clojars. 33 | 34 | ``` shell 35 | make deploy 36 | ``` 37 | 38 | ## Contribute 39 | Any Merge Request with sweetness will be welcome. 40 | 41 | ## License 42 | 43 | Copyright © 2020 44 | 45 | This program and the accompanying materials are made available under the 46 | terms of the Eclipse Public License 2.0 which is available at 47 | http://www.eclipse.org/legal/epl-2.0. 48 | 49 | This Source Code may also be made available under the following Secondary 50 | Licenses when the conditions for such availability set forth in the Eclipse 51 | Public License, v. 2.0 are satisfied: GNU General Public License as published by 52 | the Free Software Foundation, either version 2 of the License, or (at your 53 | option) any later version, with the GNU Classpath Exception which is available 54 | at https://www.gnu.org/software/classpath/license.html. 55 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject tadam-core "0.4.4" 2 | :description "Tadam Framework Core: Library to create dynamic pages" 3 | :url "https://github.com/tadam-framework/tadam-core" 4 | :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0" 5 | :url "https://www.eclipse.org/legal/epl-2.0/"} 6 | :dependencies [;; Clojure 7 | [org.clojure/clojure "1.10.1"] 8 | ;; HTTP Server 9 | [ring "1.7.1"] 10 | ;; Templates 11 | [selmer "1.12.12"] 12 | [markdown-clj "1.10.1"] 13 | ;; JSON encoding 14 | [cheshire "5.9.0"] 15 | ;; Validations 16 | [jkkramer/verily "0.6.0"] 17 | ;; Migrations 18 | [migratus "1.2.4"] 19 | ;; Module is dedicated to cryptographic API 20 | [buddy/buddy-core "1.6.0"] 21 | [buddy/buddy-hashers "1.4.0"] 22 | ;; Send emails 23 | [com.draines/postal "2.0.3"] 24 | ;; Linter 25 | [clj-kondo "RELEASE"]] 26 | :plugins [;; DEV TOOLS 27 | ;;; Check idiomatic bug 28 | [lein-kibit "0.1.7"]] 29 | ;; ALIAS 30 | :aliases {"check-idiomatic" ["kibit" "src"] 31 | "check-lint" ["run" "-m" "clj-kondo.main" "--lint" "src"]} 32 | :repl-options {:init-ns tadam.core}) 33 | -------------------------------------------------------------------------------- /resources/html/simple.html: -------------------------------------------------------------------------------- 1 |

Title

Tadam is Awesome

Website

2 | -------------------------------------------------------------------------------- /resources/html/with-param.html: -------------------------------------------------------------------------------- 1 |

Title

Tadam is {{ rating }}

Website

2 | -------------------------------------------------------------------------------- /resources/markdown/simple.md: -------------------------------------------------------------------------------- 1 | # Title 2 | 3 | Hello **world** 4 | -------------------------------------------------------------------------------- /resources/markdown/with-param.md: -------------------------------------------------------------------------------- 1 | # Title 2 | 3 | Tadam is {{ rating }} 4 | 5 | [Website]({{ url }}) 6 | -------------------------------------------------------------------------------- /src/tadam/core.clj: -------------------------------------------------------------------------------- 1 | (ns tadam.core) -------------------------------------------------------------------------------- /src/tadam/db.clj: -------------------------------------------------------------------------------- 1 | (ns tadam.db 2 | (:require 3 | [migratus.core :as migratus] 4 | [clojure.java.jdbc :as j] 5 | [buddy.hashers :as hashers])) 6 | 7 | (defn cast-data-db 8 | "Cast data from project.clj and sets SQLite path to point to the resources folder" 9 | [raw-data] 10 | (if-not (nil? raw-data) 11 | (let [cast-data (clojure.edn/read-string raw-data)] 12 | (assoc cast-data :subname (.getFile (clojure.java.io/resource (:subname cast-data))))))) 13 | 14 | (def db (cast-data-db "")) 15 | 16 | ;;;; QUERIES 17 | 18 | (defn query_all 19 | "Query in database with multiple results" 20 | [sql] 21 | (j/query db sql)) 22 | 23 | (defn query_one 24 | "Query in database with one result" 25 | [sql] 26 | (into {} (query_all sql))) 27 | 28 | (defn insert 29 | "Insert in database" 30 | [table data] 31 | (j/insert-multi! db table data)) 32 | 33 | (defn update 34 | "Update in database" 35 | [table data where] 36 | (j/update! db table data where)) 37 | 38 | (defn delete 39 | "Delete in database" 40 | [table data where] 41 | (j/delete! db table data where)) 42 | 43 | ;;;; END QUERIES 44 | 45 | ;;;; MIGRATIONS 46 | 47 | (def config-migrations {:store :database 48 | :migration-dir "migrations/" 49 | :init-script "init.sql" 50 | :init-in-transaction? false 51 | :db db}) 52 | (defn migrate 53 | "Migrate" 54 | [] 55 | (migratus/migrate config-migrations)) 56 | 57 | (defn rollback 58 | "Rollback" 59 | [] 60 | (migratus/rollback config-migrations)) 61 | 62 | ;;;; END MIGRATIONS 63 | 64 | ;;;; SUPERUSERS 65 | (defmacro prn-console 66 | "Prints text by console without double quotes with new line." 67 | [nsym] `(println "" ~(name nsym) "")) 68 | 69 | (defn createsuperuser 70 | "Create superuser" 71 | [] 72 | ;; Get first name 73 | (prn-console "> First name:") 74 | (let [first-name (read-line)] 75 | ;; Get email 76 | (prn-console "> E-mail: ") 77 | (let [email (read-line)] 78 | ;; Get password 79 | (prn-console "> Password: ") 80 | (let [password (read-line)] 81 | ;; Create superuser 82 | (insert :users [{:first_name first-name :email email :password (hashers/derive password) :role_id 1 :is_active true}]) 83 | ;; Informs the user 84 | (prn-console "🎩Superuser created with great success 🥳!"))))) 85 | 86 | (defn listsuperusers 87 | "List all superusers" 88 | [] 89 | (let [all-superusers (query_all ["SELECT first_name, email FROM users"])] 90 | (doall (map #(prn (str (:first_name %) " - " (:email %))) all-superusers)))) 91 | ;;;; END SUPERUSERS 92 | -------------------------------------------------------------------------------- /src/tadam/email.clj: -------------------------------------------------------------------------------- 1 | (ns tadam.email 2 | (:require 3 | [postal.core :refer [send-message]])) 4 | 5 | (defn send-email 6 | "Send email" 7 | [config to subject content-html content-plain] 8 | (send-message {:host (:smtp-host config) 9 | :user (:smtp-user config) 10 | :pass (:smtp-password config) 11 | :tls (:smtp-tls config) 12 | :port (:smtp-port config)} 13 | {:from (:smtp-from config) 14 | :to to 15 | :subject subject 16 | :type "text/html; charset=utf-8" 17 | :body [:alternative 18 | {:type "text/plain;charset=utf-8" 19 | :content content-plain} 20 | {:type "text/html;charset=utf-8" 21 | :content content-html}]})) 22 | -------------------------------------------------------------------------------- /src/tadam/forms.clj: -------------------------------------------------------------------------------- 1 | (ns tadam.forms 2 | (:require 3 | [jkkramer.verily :as v] 4 | [tadam.utils :refer [lazy-contains?]])) 5 | 6 | (defn validate 7 | "From some parameters and rules, return a hashmap with the validations" 8 | [params rules] 9 | (let [;; Get all errors from verily 10 | my-validations (v/validate (clojure.walk/keywordize-keys params) rules) 11 | ;; Get keys with errors 12 | my-keys (distinct (flatten (map :keys my-validations)))] 13 | ;; Return hashmap 14 | {:errors (into {} (map (fn [key] (assoc {} key (vec (map (fn [validation-filter] (:msg validation-filter)) (filter (fn [validation] (lazy-contains? (:keys validation) key)) my-validations))))) my-keys))})) 15 | -------------------------------------------------------------------------------- /src/tadam/responses.clj: -------------------------------------------------------------------------------- 1 | (ns tadam.responses 2 | (:require 3 | [ring.util.response :as ring-response])) 4 | 5 | (def headers {"X-Powered-By" "Clojure/Tadam" 6 | "Content-Type" "text/html"}) 7 | 8 | (defn response 9 | "Return response" 10 | ([req body] 11 | {:status 200 12 | :headers headers 13 | :body body 14 | :session (-> req :session)}) 15 | ([req body status] 16 | {:status status 17 | :headers headers 18 | :body body 19 | :session (-> req :session)}) 20 | ([req body status content-type] 21 | {:status status 22 | :headers (assoc headers "Content-Type" content-type) 23 | :body body 24 | :session (-> req :session)})) 25 | 26 | (defn redirect 27 | "303 See Other" 28 | ([req url] 29 | (-> (ring-response/redirect url) 30 | (assoc :session (:session req)) 31 | (assoc :status 303))) 32 | ([req url status] 33 | (-> (ring-response/redirect url) 34 | (assoc :session (:session req)) 35 | (assoc :status status)))) 36 | 37 | (defn redirect-permanent 38 | "308 Permanent Redirect" 39 | [req url] 40 | (redirect req url 308)) 41 | -------------------------------------------------------------------------------- /src/tadam/sessions.clj: -------------------------------------------------------------------------------- 1 | (ns tadam.sessions) 2 | 3 | (defn add-session 4 | "Add session in request" 5 | [req key value] 6 | (assoc-in req [:session key] value)) 7 | 8 | (defn get-key-session 9 | "Get value from key session" 10 | [req key] 11 | (-> req :session key)) 12 | 13 | (defn session? 14 | "Check if exist session" 15 | [req key] 16 | (not (nil? (get-key-session req key)))) 17 | 18 | (defn delete-key-session 19 | "Delete session from request" 20 | [req key] 21 | (update-in req [:session] dissoc key)) 22 | 23 | (defn delete-sessions 24 | "Delete all sessions from request" 25 | [req] 26 | (assoc req :session nil)) 27 | -------------------------------------------------------------------------------- /src/tadam/templates.clj: -------------------------------------------------------------------------------- 1 | (ns tadam.templates 2 | (:require 3 | [tadam.responses :refer [response]] 4 | [clojure.java.io :refer [resource]] 5 | [selmer.parser :as s] 6 | [markdown.core :refer [md-to-html-string]] 7 | [cheshire.core :refer [generate-string]])) 8 | 9 | ;; Cache off 10 | (s/cache-off!) 11 | ;; Path templates 12 | (s/set-resource-path! (resource "templates")) 13 | 14 | (defn render-template 15 | "Render template with params" 16 | [template params] 17 | (s/render-file template params)) 18 | 19 | (defn render-HTML 20 | "Render to HTML" 21 | ([req template params] 22 | (response req (s/render-file template params)))) 23 | 24 | (defn render-404 25 | "Render 404 HTML" 26 | ([req template params] 27 | (response req (s/render-file template params) 404))) 28 | 29 | (defn render-markdown 30 | "Render markdown to HTML" 31 | [req template params] 32 | (response req (md-to-html-string (s/render (slurp template) params)))) 33 | 34 | (defn render-JSON 35 | "Render JSON" 36 | ([req hash-map] 37 | (response req (generate-string hash-map) 200 "application/json")) 38 | ([req hash-map status] 39 | (response req (generate-string hash-map) status "application/json"))) 40 | -------------------------------------------------------------------------------- /src/tadam/utils.clj: -------------------------------------------------------------------------------- 1 | (ns tadam.utils 2 | (:require 3 | [cheshire.core :refer [parse-string]])) 4 | 5 | (defn is-post 6 | "Check if request is POST" 7 | [req] 8 | (= (req :request-method) :post)) 9 | 10 | (defn get-JSON 11 | "Get JSON from request" 12 | [req] 13 | (parse-string (slurp (:body req)) true)) 14 | 15 | (defn get-header 16 | "Get header value from request" 17 | [req key] 18 | (-> req :headers (get key))) 19 | 20 | (defn lazy-contains? 21 | "Check if contains lazy ignore" 22 | [col key] 23 | (some #{key} col)) 24 | -------------------------------------------------------------------------------- /test/tadam/core_test.clj: -------------------------------------------------------------------------------- 1 | (ns tadam.core-test 2 | (:require [clojure.test :refer :all] 3 | [tadam.core :refer :all])) 4 | 5 | ;; (deftest a-test 6 | ;; (testing "FIXME, I fail." 7 | ;; (is (= 0 1)))) 8 | -------------------------------------------------------------------------------- /test/tadam/templates_test.clj: -------------------------------------------------------------------------------- 1 | (ns tadam.templates-test 2 | (:require [clojure.test :refer :all] 3 | [tadam.templates :as templates] 4 | [clojure.java.io :refer [resource]])) 5 | 6 | (deftest render-template 7 | (testing "Simple" 8 | (is (= (templates/render-template (resource "html/simple.html") {}) "

Title

Tadam is Awesome

Website

\n"))) 9 | (testing "With param" 10 | (is (= (templates/render-template (resource "html/with-param.html") {:rating "Awesome" :url "https://tadam-framework.dev"}) "

Title

Tadam is Awesome

Website

\n")))) 11 | 12 | (deftest render-HTML 13 | (testing "Simple" 14 | (is (= (templates/render-HTML {:req "test"} (resource "html/simple.html") {}) {:status 200, :headers {"X-Powered-By" "Clojure/Tadam", "Content-Type" "text/html"}, :body "

Title

Tadam is Awesome

Website

\n", :session nil}))) 15 | (testing "With param" 16 | (is (= (templates/render-HTML {:req "test"} (resource "html/with-param.html") {:rating "Awesome" :url "https://tadam-framework.dev"}) {:status 200, :headers {"X-Powered-By" "Clojure/Tadam", "Content-Type" "text/html"}, :body "

Title

Tadam is Awesome

Website

\n", :session nil})))) 17 | 18 | (deftest render-404 19 | (testing "Simple" 20 | (is (= (templates/render-404 {:req "test"} (resource "html/simple.html") {}) {:status 404, :headers {"X-Powered-By" "Clojure/Tadam", "Content-Type" "text/html"}, :body "

Title

Tadam is Awesome

Website

\n", :session nil}))) 21 | (testing "With param" 22 | (is (= (templates/render-404 {:req "test"} (resource "html/with-param.html") {:rating "Awesome" :url "https://tadam-framework.dev"}) {:status 404, :headers {"X-Powered-By" "Clojure/Tadam", "Content-Type" "text/html"}, :body "

Title

Tadam is Awesome

Website

\n", :session nil})))) 23 | 24 | (deftest render-markdown 25 | (testing "Simple" 26 | (is (= (templates/render-markdown {:req "test"} (resource "markdown/simple.md") {}) {:status 200, :headers {"X-Powered-By" "Clojure/Tadam", "Content-Type" "text/html"}, :body "

Title

Hello world

", :session nil}))) 27 | (testing "With param" 28 | (is (= (templates/render-markdown {:req "test"} (resource "markdown/with-param.md") {:rating "Awesome" :url "https://tadam-framework.dev"}) {:status 200, :headers {"X-Powered-By" "Clojure/Tadam", "Content-Type" "text/html"}, :body "

Title

Tadam is Awesome

Website

", :session nil})))) 29 | 30 | (deftest render-json 31 | (testing "Simple" 32 | (is (= (templates/render-JSON {:req "test"} {:name "Tadam" :type "Framework"}) {:status 200, :headers {"X-Powered-By" "Clojure/Tadam", "Content-Type" "application/json"}, :body "{\"name\":\"Tadam\",\"type\":\"Framework\"}", :session nil})))) 33 | --------------------------------------------------------------------------------