├── .gitignore ├── LICENSE ├── README.md ├── domain-subdomain ├── .gitignore ├── README.md ├── aah.project ├── app │ ├── controllers │ │ ├── admin │ │ │ └── app.go │ │ ├── app.go │ │ └── wildcard │ │ │ └── app.go │ ├── init.go │ └── models │ │ └── greet.go ├── config │ ├── aah.conf │ ├── env │ │ ├── dev.conf │ │ └── prod.conf │ ├── routes.conf │ └── security.conf ├── go.mod ├── i18n │ └── messages.en ├── static │ ├── css │ │ └── aah.css │ ├── img │ │ ├── aah-framework-logo.png │ │ └── favicon.ico │ ├── js │ │ └── aah.js │ └── robots.txt └── views │ ├── common │ ├── error_footer.html │ ├── error_header.html │ ├── footer_scripts.html │ └── head_tags.html │ ├── errors │ ├── 404.html │ └── 500.html │ ├── layouts │ └── master.html │ └── pages │ ├── admin │ └── app │ │ └── dashboard.html │ ├── app │ └── index.html │ └── wildcard │ └── app │ └── entry.html ├── form-based-auth ├── .gitignore ├── README.md ├── aah.project ├── app │ ├── controllers │ │ ├── admin │ │ │ └── dashboard.go │ │ └── app.go │ ├── init.go │ ├── models │ │ ├── greet.go │ │ └── user.go │ └── security │ │ ├── form_authentication_provider.go │ │ └── form_authorization_provider.go ├── config │ ├── aah.conf │ ├── env │ │ ├── dev.conf │ │ └── prod.conf │ ├── routes.conf │ └── security.conf ├── go.mod ├── i18n │ └── messages.en ├── static │ ├── css │ │ └── aah.css │ ├── img │ │ ├── aah-framework-logo.png │ │ └── favicon.ico │ ├── js │ │ └── aah.js │ └── robots.txt └── views │ ├── common │ ├── error_footer.html │ ├── error_header.html │ ├── footer_scripts.html │ └── head_tags.html │ ├── errors │ ├── 404.html │ └── 500.html │ ├── layouts │ └── master.html │ └── pages │ ├── access-denied.html │ ├── admin │ └── dashboard │ │ └── index.html │ └── app │ ├── index.html │ ├── login.html │ └── manageusers.html ├── form-fileupload ├── .gitignore ├── README.md ├── aah.project ├── app │ ├── controllers │ │ └── app.go │ ├── init.go │ ├── models │ │ └── greet.go │ └── util │ │ └── util.go ├── config │ ├── aah.conf │ ├── env │ │ ├── dev.conf │ │ └── prod.conf │ ├── routes.conf │ └── security.conf ├── go.mod ├── i18n │ └── messages.en ├── static │ ├── css │ │ └── aah.css │ ├── img │ │ ├── aah-framework-logo.png │ │ └── favicon.ico │ ├── js │ │ └── aah.js │ └── robots.txt └── views │ ├── common │ ├── error_footer.html │ ├── error_header.html │ ├── footer_scripts.html │ └── head_tags.html │ ├── errors │ ├── 404.html │ └── 500.html │ ├── layouts │ └── master.html │ └── pages │ └── app │ ├── fileupload.html │ └── index.html ├── form ├── .gitignore ├── README.md ├── aah.project ├── app │ ├── controllers │ │ └── app.go │ ├── init.go │ └── models │ │ ├── greet.go │ │ └── user.go ├── config │ ├── aah.conf │ ├── env │ │ ├── dev.conf │ │ └── prod.conf │ ├── routes.conf │ └── security.conf ├── go.mod ├── i18n │ └── messages.en ├── static │ ├── css │ │ └── aah.css │ ├── img │ │ ├── aah-framework-logo.png │ │ └── favicon.ico │ ├── js │ │ └── aah.js │ └── robots.txt └── views │ ├── common │ ├── error_footer.html │ ├── error_header.html │ ├── footer_scripts.html │ └── head_tags.html │ ├── errors │ ├── 404.html │ └── 500.html │ ├── layouts │ └── master.html │ └── pages │ └── app │ ├── index.html │ └── userprofile.html ├── i18n-url-path-param ├── .gitignore ├── README.md ├── aah.project ├── app │ ├── controllers │ │ └── app.go │ └── init.go ├── config │ ├── aah.conf │ ├── env │ │ ├── dev.conf │ │ └── prod.conf │ ├── routes.conf │ └── security.conf ├── go.mod ├── i18n │ ├── messages.de-DE │ ├── messages.en │ ├── messages.es-ES │ ├── messages.es-MX │ ├── messages.ja │ └── messages.zh-CN ├── static │ ├── css │ │ └── aah.css │ ├── img │ │ ├── aah-framework-logo.png │ │ └── favicon.ico │ ├── js │ │ └── aah.js │ └── robots.txt └── views │ ├── common │ ├── error_footer.html │ ├── error_header.html │ ├── footer_scripts.html │ └── head_tags.html │ ├── errors │ ├── 404.html │ └── 500.html │ ├── layouts │ └── master.html │ └── pages │ └── app │ └── index.html ├── i18n-url-query-param ├── .gitignore ├── README.md ├── aah.project ├── app │ ├── controllers │ │ └── app.go │ └── init.go ├── config │ ├── aah.conf │ ├── env │ │ ├── dev.conf │ │ └── prod.conf │ ├── routes.conf │ └── security.conf ├── go.mod ├── i18n │ ├── messages.de-DE │ ├── messages.en │ ├── messages.es-ES │ ├── messages.es-MX │ ├── messages.ja │ └── messages.zh-CN ├── static │ ├── css │ │ └── aah.css │ ├── img │ │ ├── aah-framework-logo.png │ │ └── favicon.ico │ ├── js │ │ └── aah.js │ └── robots.txt └── views │ ├── common │ ├── error_footer.html │ ├── error_header.html │ ├── footer_scripts.html │ └── head_tags.html │ ├── errors │ ├── 404.html │ └── 500.html │ ├── layouts │ └── master.html │ └── pages │ └── app │ └── index.html ├── oauth2-social-login ├── .gitignore ├── README.md ├── aah.project ├── app │ ├── controllers │ │ └── app.go │ ├── init.go │ ├── models │ │ └── greet.go │ └── security │ │ ├── authorization_provider.go │ │ ├── facebook │ │ └── subject_principal_provider.go │ │ ├── github │ │ └── subject_principal_provider.go │ │ ├── google │ │ └── subject_principal_provider.go │ │ └── post_auth_event.go ├── config │ ├── aah.conf │ ├── env │ │ ├── dev.conf │ │ └── prod.conf │ ├── routes.conf │ └── security.conf ├── go.mod ├── i18n │ └── messages.en ├── static │ ├── css │ │ └── aah.css │ ├── img │ │ ├── aah-framework-logo.png │ │ └── favicon.ico │ ├── js │ │ └── aah.js │ └── robots.txt └── views │ ├── common │ ├── error_footer.html │ ├── error_header.html │ ├── footer_scripts.html │ └── head_tags.html │ ├── errors │ ├── 404.html │ └── 500.html │ ├── layouts │ └── master.html │ └── pages │ └── app │ ├── index.html │ └── success.html ├── rest-api-basic-auth ├── .gitignore ├── README.md ├── aah.project ├── app │ ├── controllers │ │ ├── app.go │ │ └── info.go │ ├── init.go │ ├── models │ │ ├── greet.go │ │ └── user.go │ └── security │ │ ├── basic_authentication_provider.go │ │ └── basic_authorization_provider.go ├── config │ ├── aah.conf │ ├── env │ │ ├── dev.conf │ │ └── prod.conf │ ├── routes.conf │ └── security.conf └── go.mod ├── rest-api-jwt-auth ├── .gitignore ├── README.md ├── aah.project ├── app │ ├── controllers │ │ ├── app.go │ │ └── info.go │ ├── init.go │ ├── models │ │ ├── greet.go │ │ └── user.go │ └── security │ │ ├── authentication_provider.go │ │ ├── authorization_provider.go │ │ └── jwt.go ├── config │ ├── aah.conf │ ├── env │ │ ├── dev.conf │ │ └── prod.conf │ ├── routes.conf │ └── security.conf └── go.mod ├── rest-api ├── .gitignore ├── README.md ├── aah.project ├── app │ ├── controllers │ │ ├── app.go │ │ └── post.go │ ├── init.go │ └── models │ │ ├── greet.go │ │ └── post.go ├── config │ ├── aah.conf │ ├── env │ │ ├── dev.conf │ │ └── prod.conf │ ├── routes.conf │ └── security.conf └── go.mod └── simple-chat ├── .gitignore ├── README.md ├── aah.project ├── app ├── controllers │ └── app.go ├── init.go └── websockets │ ├── event.go │ └── simple_chat.go ├── config ├── aah.conf ├── env │ ├── dev.conf │ └── prod.conf ├── routes.conf └── security.conf ├── go.mod ├── i18n └── messages.en ├── static ├── css │ └── aah.css ├── img │ ├── aah-framework-logo.png │ ├── aah-logo-64x64.png │ └── favicon.ico ├── js │ └── aah.js └── robots.txt └── views ├── common ├── error_footer.html ├── error_header.html ├── footer_scripts.html └── head_tags.html ├── errors ├── 404.html └── 500.html ├── layouts └── master.html └── pages └── app ├── index.html └── simplechatdemo.html /.gitignore: -------------------------------------------------------------------------------- 1 | # .gitignore config 2 | 3 | go.sum 4 | *.pid 5 | 6 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 7 | *.o 8 | *.a 9 | *.so 10 | 11 | # Folders 12 | _obj 13 | _test 14 | 15 | # Architecture specific extensions/prefixes 16 | *.[568vq] 17 | [568vq].out 18 | 19 | *.cgo1.go 20 | *.cgo2.c 21 | _cgo_defun.c 22 | _cgo_gotypes.go 23 | _cgo_export.* 24 | 25 | _testmain.go 26 | 27 | *.exe 28 | *.test 29 | *.prof 30 | 31 | # Binaries for programs and plugins 32 | *.exe 33 | *.dll 34 | *.so 35 | *.dylib 36 | 37 | # Test binary, build with `go test -c` 38 | *.test 39 | 40 | # Output of the go coverage tool, specifically when used with LiteIDE 41 | *.out 42 | 43 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 44 | .glide/ 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Jeevanandam M., https://github.com/jeevatkm, jeeva@myjeeva.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

Examples of aah Go web framework

4 |

5 |

6 |

Content License: CC BY-SA 4.0 Content License: CC BY-SA 4.0

7 |

8 |
9 |

10 | aah examples is organized & structured version wise branch vMajorVersion.MinorVersion.x, get into respective branch as required.
E.g. v0.7.x, v0.8.x, and so on.

11 | 12 | -------------------------------------------------------------------------------- /domain-subdomain/.gitignore: -------------------------------------------------------------------------------- 1 | # aah framework application - .gitignore 2 | 3 | aah.go 4 | *.pid 5 | build/ 6 | aah_*_vfs.go 7 | app/generated 8 | vendor/*/ 9 | # aah application - end 10 | 11 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 12 | *.o 13 | *.a 14 | *.so 15 | 16 | # Folders 17 | _obj 18 | _test 19 | 20 | # Architecture specific extensions/prefixes 21 | *.[568vq] 22 | [568vq].out 23 | 24 | *.cgo1.go 25 | *.cgo2.c 26 | _cgo_defun.c 27 | _cgo_gotypes.go 28 | _cgo_export.* 29 | 30 | _testmain.go 31 | 32 | *.exe 33 | *.test 34 | *.prof 35 | -------------------------------------------------------------------------------- /domain-subdomain/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

Example - Domain, Subdomain and Wildcard Subdomain

4 |

5 | 6 | This example application gives insights on how to use domains, subdomains and wildcard subdomains with aah framework. Reference to [Routes Config](https://docs.aahframework.org/routing.html). 7 | 8 | ### Get aah examples 9 | 10 | ```bash 11 | git clone https://github.com/go-aah/examples.git aah-examples 12 | ``` 13 | 14 | ### Configure local DNS mapping 15 | 16 | Firstly, configure `hosts` file. The purpose is to do local DNS mapping for `sample.com`. This step is not applicable for production. Typically, these settings happen in domain DNS manager. Learn more about [Wildcard DNS - wikipedia](https://en.wikipedia.org/wiki/Wildcard_DNS_record) 17 | 18 | This [rackspace article](https://support.rackspace.com/how-to/modify-your-hosts-file/) covers the steps to modify-your-hosts-file for Mac, Linux and Windows. 19 | 20 | ```bash 21 | 127.0.0.1 sample.com admin.sample.com username1.sample.com username2.sample.com username3.sample.com 22 | ``` 23 | 24 | ### Run this example 25 | 26 | ```bash 27 | cd aah-examples/domain-subdomain 28 | aah run 29 | ``` 30 | 31 | ### Visit these URLs 32 | 33 | * http://sample.com:8080 34 | * http://admin.sample.com:8080 35 | * http://username1.sample.com:8080 36 | * http://username2.sample.com:8080 37 | * http://username3.sample.com:8080 38 | 39 | -------------------------------------------------------------------------------- /domain-subdomain/app/controllers/admin/app.go: -------------------------------------------------------------------------------- 1 | package admin 2 | 3 | import "aahframe.work" 4 | 5 | // AppController is Admin App controller. 6 | type AppController struct { 7 | *aah.Context 8 | } 9 | 10 | // Dashboard method is admin dashboard page for examples. 11 | func (c *AppController) Dashboard() { 12 | 13 | c.Reply().Ok().HTML(aah.Data{ 14 | "Subdomain": c.Subdomain(), 15 | "Message": "I'm in admin dashboard page", 16 | }) 17 | 18 | } 19 | -------------------------------------------------------------------------------- /domain-subdomain/app/controllers/app.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "aahframe.work" 5 | "aahframework.org/examples/domain-subdomain/app/models" 6 | ) 7 | 8 | // AppController struct application controller 9 | type AppController struct { 10 | *aah.Context 11 | } 12 | 13 | // Index method is application home page. 14 | func (c *AppController) Index() { 15 | data := aah.Data{ 16 | "Greet": models.Greet{ 17 | Message: "Example - Domain, Subdomain, and Wildcard Subdomain", 18 | }, 19 | } 20 | 21 | c.Reply().Ok().HTML(data) 22 | } 23 | -------------------------------------------------------------------------------- /domain-subdomain/app/controllers/wildcard/app.go: -------------------------------------------------------------------------------- 1 | package wildcard 2 | 3 | import ( 4 | "aahframe.work" 5 | "aahframework.org/examples/domain-subdomain/app/controllers" 6 | ) 7 | 8 | // AppController is wildcard controller. 9 | type AppController struct { 10 | controllers.AppController 11 | } 12 | 13 | // Entry method is wildcard subdomain controller for examples. 14 | func (c *AppController) Entry() { 15 | 16 | c.Reply().Ok().HTML(aah.Data{ 17 | "Subdomain": c.Subdomain(), 18 | "Message": "I'm in wildcard app controller page", 19 | }) 20 | 21 | } 22 | -------------------------------------------------------------------------------- /domain-subdomain/app/models/greet.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // Greet holds the greeting message. 4 | type Greet struct { 5 | Message string `json:"message"` 6 | } 7 | -------------------------------------------------------------------------------- /domain-subdomain/config/env/dev.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Development Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | dev { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Log Configuration 9 | # 10 | # Doc: https://docs.aahframework.org/logging.html 11 | # Doc: https://docs.aahframework.org/log-config.html 12 | # ----------------------------------------------------------------------------- 13 | log { 14 | receiver = "console" 15 | level = "debug" 16 | format = "text" 17 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 18 | color = true 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /domain-subdomain/config/env/prod.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Production Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | prod { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Runtime configuration 9 | # Doc: https://docs.aahframework.org/app-config.html#section-runtime 10 | # ----------------------------------------------------------------------------- 11 | runtime { 12 | debug { 13 | strip_src_base = true 14 | } 15 | } 16 | 17 | # ----------------------------------------------------------------------------- 18 | # Log Configuration 19 | # 20 | # Doc: https://docs.aahframework.org/logging.html 21 | # Doc: https://docs.aahframework.org/log-config.html 22 | # ----------------------------------------------------------------------------- 23 | log { 24 | receiver = "file" 25 | file = "domain-subdomain.log" 26 | level = "warn" 27 | format = "text" 28 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 29 | color = false 30 | rotate { 31 | policy = "daily" 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /domain-subdomain/config/security.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # domain-subdomain - Application Security Configuration 3 | # 4 | # Refer documentation to explore and customize the configurations. 5 | # Doc: https://docs.aahframework.org/security-config.html 6 | # ----------------------------------------------------------------------------- 7 | security { 8 | # ----------------------------------------------------------------------------- 9 | # Session configuration 10 | # HTTP state management across multiple requests. 11 | # 12 | # Doc: https://docs.aahframework.org/security-config.html#section-session 13 | # ----------------------------------------------------------------------------- 14 | session { 15 | mode = "stateful" 16 | store { 17 | type = "cookie" 18 | } 19 | sign_key = "6f33a3752fca7731618b75579330a4ababa6a1769fc8f23703ebb9c71e04b674" 20 | enc_key = "856766d61c6445ed267cabfffffce27a" 21 | } 22 | 23 | # --------------------------------------------------------------------------- 24 | # HTTP Secure Header(s) 25 | # Application security headers with many safe defaults. 26 | # 27 | # Doc: https://docs.aahframework.org/security-config.html#section-http-header 28 | # 29 | # Tip: Quick way to verify secure headers - https://securityheaders.io 30 | # --------------------------------------------------------------------------- 31 | http_header { 32 | enable = true 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /domain-subdomain/go.mod: -------------------------------------------------------------------------------- 1 | module aahframework.org/examples/domain-subdomain 2 | 3 | require ( 4 | aahframe.work v0.12.2 5 | aahframe.work/minify/html v0.2.0 6 | ) 7 | -------------------------------------------------------------------------------- /domain-subdomain/i18n/messages.en: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for domain-subdomain application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | label { 8 | pages { 9 | app { 10 | index { 11 | title = "Example Domain, Subdomain and Wildcard Subdomain - Home | aah Go web framework" 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /domain-subdomain/static/css/aah.css: -------------------------------------------------------------------------------- 1 | /* 2 | Minimal aah framework application template CSS. 3 | Based on your need choose your CSS framework. 4 | */ 5 | 6 | html { 7 | font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; 8 | -webkit-text-size-adjust: 100%; 9 | -ms-text-size-adjust: 100%; 10 | } 11 | 12 | body { 13 | margin: 0; 14 | } 15 | 16 | .container { 17 | padding-right: 15px; 18 | padding-left: 15px; 19 | margin-right: auto; 20 | margin-left: auto; 21 | } 22 | @media (min-width: 992px) { 23 | .container { 24 | width: 970px; 25 | } 26 | } 27 | @media (min-width: 1200px) { 28 | .container { 29 | width: 1170px; 30 | } 31 | } 32 | 33 | .row { 34 | margin-right: -15px; 35 | margin-left: -15px; 36 | } 37 | 38 | .text-center { 39 | text-align: center; 40 | } 41 | 42 | .welcome-msg { 43 | padding-top: 30px; 44 | padding-bottom: 30px; 45 | margin-bottom: 30px; 46 | color: inherit; 47 | } 48 | 49 | .tm-25 { 50 | margin-top: 25px; 51 | } 52 | -------------------------------------------------------------------------------- /domain-subdomain/static/img/aah-framework-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/domain-subdomain/static/img/aah-framework-logo.png -------------------------------------------------------------------------------- /domain-subdomain/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/domain-subdomain/static/img/favicon.ico -------------------------------------------------------------------------------- /domain-subdomain/static/js/aah.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/domain-subdomain/static/js/aah.js -------------------------------------------------------------------------------- /domain-subdomain/static/robots.txt: -------------------------------------------------------------------------------- 1 | # Prevents all robots visiting your site. 2 | User-agent: * 3 | Disallow: / 4 | -------------------------------------------------------------------------------- /domain-subdomain/views/common/error_footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /domain-subdomain/views/common/error_header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ .Error.Code }} {{ .Error.Message }} 8 | 9 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /domain-subdomain/views/common/footer_scripts.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /domain-subdomain/views/common/head_tags.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /domain-subdomain/views/errors/404.html: -------------------------------------------------------------------------------- 1 | {{ include "/common/error_header.html" . -}} 2 |
{{ with .Error }} 3 |
4 |
5 | {{ .Code }} {{ .Message }} 6 |
7 |
{{ end }} 8 |
9 | {{ include "/common/error_footer.html" . -}} 10 | -------------------------------------------------------------------------------- /domain-subdomain/views/errors/500.html: -------------------------------------------------------------------------------- 1 | {{ include "/common/error_header.html" . -}} 2 |
{{ with .Error }} 3 |
4 |
5 | {{ .Code }} {{ .Message }} 6 |
7 |
{{ end }} 8 |
9 | {{ include "/common/error_footer.html" . -}} 10 | -------------------------------------------------------------------------------- /domain-subdomain/views/layouts/master.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ template "title" . }} 8 | {{ include "/common/head_tags.html" . }} 9 | 10 | 11 | {{ template "body" . -}} 12 | {{ include "/common/footer_scripts.html" . }} 13 | 14 | 15 | -------------------------------------------------------------------------------- /domain-subdomain/views/pages/admin/app/dashboard.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | Admin Dashboard - aah framework: Examples of Domain, Subdomain and Wildcard Subdomain 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 |
7 |
8 |

Example - Domain, Subdomain, and Wildcard Subdomain

9 |
10 | Host/Domain: {{ .Host }}
11 | Subdomain: {{ .Subdomain }}
12 | Message: {{ .Message }}
13 |
14 | 15 |
16 | Home 17 |
18 |
19 |
20 | {{- end }} 21 | -------------------------------------------------------------------------------- /domain-subdomain/views/pages/app/index.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | {{ i18n . "label.pages.app.index.title" }} 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 |
7 |
8 | aah framework logo 9 |

{{ .Greet.Message }}

10 |
11 | Host/Domain: {{ .Host }} 12 |
13 | 14 |
15 |

Named Subdomain

16 | 19 |
20 | 21 |
22 |

Wildcard Subdomain

23 | 29 |
30 |
31 |
32 | {{- end }} 33 | -------------------------------------------------------------------------------- /domain-subdomain/views/pages/wildcard/app/entry.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | Wildcard Entry - aah framework: Example Domain, Subdomain and Wildcard Subdomain 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 |
7 |
8 |

Examples - Domain, Subdomain, and Wildcard Subdomain

9 |
10 | Host/Domain: {{ .Host }}
11 | Subdomain: {{ .Subdomain }}
12 | Message: {{ .Message }}
13 |
14 | 15 |
16 | Home 17 |
18 |
19 |
20 | {{- end }} 21 | -------------------------------------------------------------------------------- /form-based-auth/.gitignore: -------------------------------------------------------------------------------- 1 | # aah framework application - .gitignore 2 | 3 | aah.go 4 | *.pid 5 | build/ 6 | aah_*_vfs.go 7 | app/generated 8 | vendor/*/ 9 | # aah application - end 10 | 11 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 12 | *.o 13 | *.a 14 | *.so 15 | 16 | # Folders 17 | _obj 18 | _test 19 | 20 | # Architecture specific extensions/prefixes 21 | *.[568vq] 22 | [568vq].out 23 | 24 | *.cgo1.go 25 | *.cgo2.c 26 | _cgo_defun.c 27 | _cgo_gotypes.go 28 | _cgo_export.* 29 | 30 | _testmain.go 31 | 32 | *.exe 33 | *.test 34 | *.prof 35 | -------------------------------------------------------------------------------- /form-based-auth/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

Example - Form based Auth

4 |

5 | 6 | This example demonstrates form based auth with aah framework. Form based auth includes authentication, route authorization via routes config, access permissions on view files and session access on View files. 7 | 8 | Learn more about [Security design](https://docs.aahframework.org/security-design.html), [Authentication](https://docs.aahframework.org/authentication.html), [Authorization](https://docs.aahframework.org/authorization.html) and [Form Auth scheme](https://docs.aahframework.org/auth-schemes/form.html). 9 | 10 | ### Get aah examples 11 | 12 | ```bash 13 | git clone https://github.com/go-aah/examples.git aah-examples 14 | ``` 15 | 16 | ### Run this example 17 | 18 | ```bash 19 | cd aah-examples/form-based-auth 20 | aah run 21 | ``` 22 | 23 | ### Visit this URL 24 | 25 | * http://localhost:8080 26 | 27 | The application will take you to the login page. From there, it is self explanatory. Happy coding! 28 | 29 | Navigate these URLs with various credentials listed on the login page. Observe the application logs to learn more. 30 | 31 | * http://localhost:8080/manage/users.html 32 | * http://localhost:8080/admin/dashboard.html 33 | * http://localhost:8080/login.html 34 | -------------------------------------------------------------------------------- /form-based-auth/app/controllers/admin/dashboard.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package admin 6 | 7 | import ( 8 | "net/http" 9 | 10 | "aahframe.work" 11 | ) 12 | 13 | // DashboardController struct demo implementation of admin scope. 14 | type DashboardController struct { 15 | *aah.Context 16 | } 17 | 18 | // Index method dispay the admin Dashboard page. 19 | func (c *DashboardController) Index() { 20 | c.Reply().Ok() 21 | } 22 | 23 | // HandleError method invoked by aah error handling flow 24 | // Doc: https://aahframework.org/error-handling.html 25 | func (c *DashboardController) HandleError(err *aah.Error) bool { 26 | switch err.Code { 27 | case http.StatusForbidden: 28 | c.Reply().Forbidden().HTMLf("/access-denied.html", nil) 29 | } 30 | return true 31 | } 32 | -------------------------------------------------------------------------------- /form-based-auth/app/controllers/app.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package controllers 6 | 7 | import ( 8 | "aahframe.work" 9 | "aahframework.org/examples/form-based-auth/app/models" 10 | ) 11 | 12 | // AppController struct application controller 13 | type AppController struct { 14 | *aah.Context 15 | } 16 | 17 | // Index method is application home page. 18 | func (c *AppController) Index() { 19 | data := aah.Data{ 20 | "Greet": models.Greet{ 21 | Message: "Welcome to aah framework - Form Based Auth Example", 22 | }, 23 | } 24 | 25 | c.Reply().Ok().HTML(data) 26 | } 27 | 28 | // BeforeLogin method action is interceptor of Login. 29 | func (c *AppController) BeforeLogin() { 30 | if c.Subject().IsAuthenticated() { 31 | c.Reply().Redirect(c.RouteURL("index")) 32 | c.Abort() 33 | } 34 | } 35 | 36 | // Login method presents the login page. 37 | func (c *AppController) Login() { 38 | c.Reply().Ok() 39 | } 40 | 41 | // Logout method does logout currently logged in subject (aka user). 42 | func (c *AppController) Logout() { 43 | c.Subject().Logout() 44 | 45 | // Send it to login page or whatever the page you have to send the user 46 | // after logout 47 | c.Reply().Redirect(c.RouteURL("login")) 48 | } 49 | 50 | // BeforeManageUsers method is action interceptor of ManageUsers. 51 | // func (c *AppController) BeforeManageUsers() { 52 | // // Checking roles and permissions 53 | // if !c.Subject().HasAnyRole("manager", "administrator") || 54 | // !c.Subject().IsPermitted("users:manage:view") { 55 | // c.Reply().Forbidden().HTMLf("/access-denied.html", nil) 56 | // c.Abort() 57 | // } 58 | // } 59 | 60 | // ManageUsers method presents the manage user page afer verifying 61 | // Authorization 62 | func (c *AppController) ManageUsers() { 63 | // looks okay, present the page 64 | c.Reply().Ok().HTML(nil) 65 | } 66 | -------------------------------------------------------------------------------- /form-based-auth/app/models/greet.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package models 6 | 7 | // Greet holds the greeting message. 8 | type Greet struct { 9 | Message string `json:"message"` 10 | } 11 | -------------------------------------------------------------------------------- /form-based-auth/app/models/user.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package models 6 | 7 | // This is for demo purpose, set of users 8 | // Typically you will be using Database, API calls, LDAP, etc to get the Authentication 9 | // Information. 10 | 11 | // Key is Email and value is User 12 | var users map[string]*User 13 | 14 | type ( 15 | // User struct hold the user details 16 | User struct { 17 | FirstName string `json:"first_name"` 18 | LastName string `json:"last_name"` 19 | Email string `json:"email"` 20 | Password string `json:"-"` 21 | IsLocked bool `json:"is_locked"` 22 | IsExpried bool `json:"is_expried"` 23 | Roles []string `json:"roles,omitempty"` 24 | Permissions []string `json:"permission,omitempty"` 25 | } 26 | ) 27 | 28 | // FindUserByEmail returns the user information for given email address. 29 | func FindUserByEmail(email string) *User { 30 | if u, found := users[email]; found { 31 | uf := *u 32 | return &uf 33 | } 34 | return nil 35 | } 36 | 37 | func init() { 38 | /* 39 | Creating User Information 40 | Learn about permission: http://docs.aahframework.org/security-permissions.html 41 | */ 42 | users = make(map[string]*User) 43 | 44 | users["user1@aahframework.org"] = &User{ 45 | FirstName: "East", 46 | LastName: "Corner", 47 | Password: "$2y$10$2A4GsJ6SmLAMvDe8XmTam.MSkKojdobBVJfIU7GiyoM.lWt.XV3H6", // welcome123 48 | Email: "user1@aahframework.org", 49 | Roles: []string{"user", "manager"}, 50 | Permissions: []string{"users:manage:view"}, 51 | } 52 | 53 | users["user2@aahframework.org"] = &User{ 54 | FirstName: "West", 55 | LastName: "Corner", 56 | Password: "$2y$10$2A4GsJ6SmLAMvDe8XmTam.MSkKojdobBVJfIU7GiyoM.lWt.XV3H6", // welcome123 57 | Email: "user2@aahframework.org", 58 | IsLocked: true, 59 | } 60 | 61 | users["user3@aahframework.org"] = &User{ 62 | FirstName: "South", 63 | LastName: "Corner", 64 | Password: "$2y$10$2A4GsJ6SmLAMvDe8XmTam.MSkKojdobBVJfIU7GiyoM.lWt.XV3H6", // welcome123 65 | Email: "user3@aahframework.org", 66 | Roles: []string{"user"}, 67 | } 68 | 69 | users["admin@aahframework.org"] = &User{ 70 | FirstName: "Admin", 71 | LastName: "Corner", 72 | Password: "$2y$10$2A4GsJ6SmLAMvDe8XmTam.MSkKojdobBVJfIU7GiyoM.lWt.XV3H6", // welcome123 73 | Email: "admin@aahframework.org", 74 | Roles: []string{"user", "administrator"}, 75 | Permissions: []string{"users:*"}, 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /form-based-auth/app/security/form_authentication_provider.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package security 6 | 7 | import ( 8 | "aahframe.work" 9 | "aahframe.work/config" 10 | "aahframe.work/security/authc" 11 | "aahframework.org/examples/form-based-auth/app/models" 12 | ) 13 | 14 | var _ authc.Authenticator = (*FormAuthenticationProvider)(nil) 15 | 16 | // FormAuthenticationProvider struct implements `authc.Authenticator` interface. 17 | type FormAuthenticationProvider struct { 18 | } 19 | 20 | // Init method initializes the FormAuthenticationProvider, this method gets called 21 | // during server start up. 22 | func (fa *FormAuthenticationProvider) Init(cfg *config.Config) error { 23 | 24 | // NOTE: Init is called on application startup 25 | 26 | return nil 27 | } 28 | 29 | // GetAuthenticationInfo method is `authc.Authenticator` interface 30 | func (fa *FormAuthenticationProvider) GetAuthenticationInfo(authcToken *authc.AuthenticationToken) (*authc.AuthenticationInfo, error) { 31 | 32 | // Form Auth Values from authcToken 33 | // authcToken.Identity => username 34 | // authcToken.Credential => passowrd 35 | 36 | user := models.FindUserByEmail(authcToken.Identity) 37 | if user == nil { 38 | // No subject exists, return nil and error 39 | return nil, authc.ErrSubjectNotExists 40 | } 41 | 42 | // User found, now create authentication info and return to the framework 43 | authcInfo := authc.NewAuthenticationInfo() 44 | authcInfo.Principals = append(authcInfo.Principals, 45 | &authc.Principal{ 46 | Value: user.Email, 47 | IsPrimary: true, 48 | Realm: "inmemory", 49 | }) 50 | authcInfo.Credential = []byte(user.Password) 51 | authcInfo.IsLocked = user.IsLocked 52 | authcInfo.IsExpired = user.IsExpried 53 | 54 | return authcInfo, nil 55 | } 56 | 57 | func PostAuthEvent(e *aah.Event) { 58 | ctx := e.Data.(*aah.Context) 59 | 60 | // Populate session info after authentication 61 | user := models.FindUserByEmail(ctx.Subject().PrimaryPrincipal().Value) 62 | ctx.Session().Set("FirstName", user.FirstName) 63 | ctx.Session().Set("LastName", user.LastName) 64 | } 65 | -------------------------------------------------------------------------------- /form-based-auth/app/security/form_authorization_provider.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package security 6 | 7 | import ( 8 | "aahframe.work/config" 9 | "aahframe.work/security/authc" 10 | "aahframe.work/security/authz" 11 | "aahframework.org/examples/form-based-auth/app/models" 12 | ) 13 | 14 | var _ authz.Authorizer = (*FormAuthorizationProvider)(nil) 15 | 16 | // FormAuthorizationProvider struct implements `authz.Authorizer` interface. 17 | type FormAuthorizationProvider struct { 18 | } 19 | 20 | // Init method initializes the FormAuthoriationProvider, this method gets called 21 | // during server start up. 22 | func (fa *FormAuthorizationProvider) Init(cfg *config.Config) error { 23 | 24 | // NOTE: Init is called on application startup 25 | 26 | return nil 27 | } 28 | 29 | // GetAuthorizationInfo method is `authz.Authorizer` interface. 30 | // 31 | // GetAuthorizationInfo method gets called after authentication is successful 32 | // to get Subject's (aka User) access control information such as roles and permissions. 33 | func (fa *FormAuthorizationProvider) GetAuthorizationInfo(authcInfo *authc.AuthenticationInfo) *authz.AuthorizationInfo { 34 | authorities := models.FindUserByEmail(authcInfo.PrimaryPrincipal().Value) 35 | 36 | authzInfo := authz.NewAuthorizationInfo() 37 | authzInfo.AddRole(authorities.Roles...) 38 | authzInfo.AddPermissionString(authorities.Permissions...) 39 | 40 | return authzInfo 41 | } 42 | -------------------------------------------------------------------------------- /form-based-auth/config/env/dev.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Development Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | dev { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Log Configuration 9 | # 10 | # Doc: https://docs.aahframework.org/logging.html 11 | # Doc: https://docs.aahframework.org/log-config.html 12 | # ----------------------------------------------------------------------------- 13 | log { 14 | receiver = "console" 15 | level = "debug" 16 | format = "text" 17 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 18 | color = true 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /form-based-auth/config/env/prod.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Production Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | prod { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Runtime configuration 9 | # Doc: https://docs.aahframework.org/app-config.html#section-runtime 10 | # ----------------------------------------------------------------------------- 11 | runtime { 12 | debug { 13 | strip_src_base = true 14 | } 15 | } 16 | 17 | # ----------------------------------------------------------------------------- 18 | # Log Configuration 19 | # 20 | # Doc: https://docs.aahframework.org/logging.html 21 | # Doc: https://docs.aahframework.org/log-config.html 22 | # ----------------------------------------------------------------------------- 23 | log { 24 | receiver = "file" 25 | file = "form-based-auth.log" 26 | level = "warn" 27 | format = "text" 28 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 29 | color = false 30 | rotate { 31 | policy = "daily" 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /form-based-auth/go.mod: -------------------------------------------------------------------------------- 1 | module aahframework.org/examples/form-based-auth 2 | 3 | require ( 4 | aahframe.work v0.12.2 5 | aahframe.work/minify/html v0.2.0 6 | ) 7 | -------------------------------------------------------------------------------- /form-based-auth/i18n/messages.en: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for form-based-auth application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | label { 8 | pages { 9 | app { 10 | index { 11 | title = "Example - Form Auth Home Page - aah Go web framework for Go" 12 | } 13 | 14 | login { 15 | title = "Example - Form Auth Login Page - aah Go web framework for Go" 16 | } 17 | 18 | manage_users { 19 | title = "Example - Manage Users - aah Go web framework for Go" 20 | } 21 | 22 | dashboard { 23 | title = "Example - Admin Dashboard - aah Go web framework for Go" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /form-based-auth/static/img/aah-framework-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/form-based-auth/static/img/aah-framework-logo.png -------------------------------------------------------------------------------- /form-based-auth/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/form-based-auth/static/img/favicon.ico -------------------------------------------------------------------------------- /form-based-auth/static/js/aah.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/form-based-auth/static/js/aah.js -------------------------------------------------------------------------------- /form-based-auth/static/robots.txt: -------------------------------------------------------------------------------- 1 | # Prevents all robots visiting your site. 2 | User-agent: * 3 | Disallow: / 4 | -------------------------------------------------------------------------------- /form-based-auth/views/common/error_footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /form-based-auth/views/common/error_header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ .Error.Code }} {{ .Error.Message }} 8 | 9 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /form-based-auth/views/common/footer_scripts.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /form-based-auth/views/common/head_tags.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /form-based-auth/views/errors/404.html: -------------------------------------------------------------------------------- 1 | {{ include "/common/error_header.html" . -}} 2 |
{{ with .Error }} 3 |
4 |
5 | {{ .Code }} {{ .Message }} 6 |
7 |
{{ end }} 8 |
9 | {{ include "/common/error_footer.html" . -}} 10 | -------------------------------------------------------------------------------- /form-based-auth/views/errors/500.html: -------------------------------------------------------------------------------- 1 | {{ include "/common/error_header.html" . -}} 2 |
{{ with .Error }} 3 |
4 |
5 | {{ .Code }} {{ .Message }} 6 |
7 |
{{ end }} 8 |
9 | {{ include "/common/error_footer.html" . -}} 10 | -------------------------------------------------------------------------------- /form-based-auth/views/layouts/master.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ template "title" . }} 8 | {{ include "/common/head_tags.html" . }} 9 | 10 | 11 | {{ template "body" . -}} 12 | {{ include "/common/footer_scripts.html" . }} 13 | 14 | 15 | -------------------------------------------------------------------------------- /form-based-auth/views/pages/access-denied.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | Access Denied 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 | 7 |
8 |
9 |

You do not have permissions to access this page.



10 | Access Denied

11 | Go to Home 12 |
13 |
14 | 15 | {{- end }} 16 | -------------------------------------------------------------------------------- /form-based-auth/views/pages/admin/dashboard/index.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | {{ i18n . "label.pages.app.dashboard.title" }} 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 | 7 |
8 |
9 |

This is admin dashboard page



10 |

Shown to users who have role "administrator"

11 |

12 |
13 |
14 |
15 |

Demo Links

16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | {{ if (ispermitted . "users:manage:view") (hasanyrole . "manager" "administrator") }} 26 | 27 | 28 | 29 | 30 | {{ end }} 31 | 32 | 33 | 34 | 35 | 36 |
LinkDescription
Manage UsersShown to users who have either "manager" or "administrator" role and permission "users:manage:view"
Home
To go to Homepage
37 |
38 |
39 |
40 |
41 | 42 | {{- end }} 43 | -------------------------------------------------------------------------------- /form-based-auth/views/pages/app/index.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | {{ i18n . "label.pages.app.index.title" }} 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 | 7 |
8 | 12 |
13 | 14 | 19 | 20 |
21 |
22 |
23 | aah framework logo 24 |

{{ .Greet.Message }}



25 | 26 |
27 | Hello {{ session . "LastName" }}, {{ session . "FirstName"}} 28 |
29 |
30 | 31 |
32 |
33 |
34 |

Demo Links

35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | {{ if hasrole . "administrator" }} 45 | 46 | 47 | 48 | 49 | {{ end }} 50 | {{ if (ispermitted . "users:manage:view") (hasanyrole . "manager" "administrator") }} 51 | 52 | 53 | 54 | 55 | {{ end }} 56 | 57 | 58 | 59 | 60 | 61 |
LinkDescription
Admin DashboardShown to users who have role "administrator"
Manage UsersShown to users who have either "manager" or "administrator" role and permission "users:manage:view"
LogoutTo logout from example application
62 |
63 |
64 |
65 |
66 | {{- end }} 67 | -------------------------------------------------------------------------------- /form-based-auth/views/pages/app/login.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | {{ i18n . "label.pages.app.login.title" }} 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 | 7 | 11 |
12 |
13 | 14 |
15 | {{ if eq (qparam . "error") "true" }} 16 |
17 | Invalid credentials. 18 |
19 | {{ end }} 20 |
21 | 26 |
27 | 28 |
29 |
30 |
31 |

Demo Users

32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
UsernamePasswordLastName, FirstName
user1@aahframework.org
Roles: user, manager | Permission: users:manage:view
welcome123Corner, East
user2@aahframework.org (user is locked state)welcome123Corner, West
user3@aahframework.org
Roles: user
welcome123Corner, South
admin@aahframework.org
Roles: user, administrator | Permission: users:*
welcome123Corner, Admin
64 |
65 |
66 |
67 | 68 | {{- end }} 69 | -------------------------------------------------------------------------------- /form-based-auth/views/pages/app/manageusers.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | {{ i18n . "label.pages.app.manage_users.title" }} 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 | 7 |
8 |
9 |

Manage Users Page


10 |

This is page shown to user who have role (manager or administrator) and permission ("users:manage:view")

11 |

12 |
13 |
14 |
15 |

Demo Links

16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | {{ if (hasrole . "administrator") (ispermitted . "users:manage:edit") }} 26 | 27 | 28 | 29 | 30 | {{ end }} 31 | 32 | 33 | 34 | 35 | 36 |
LinkDescription
Edit UserShown to users who have role `administrator` and permission `users:manage:edit`
Home
To go to Homepage
37 |
38 |
39 |
40 |
41 | 42 | {{- end }} 43 | -------------------------------------------------------------------------------- /form-fileupload/.gitignore: -------------------------------------------------------------------------------- 1 | # aah framework application - .gitignore 2 | 3 | aah.go 4 | *.pid 5 | build/ 6 | aah_*_vfs.go 7 | app/generated 8 | # aah application - end 9 | vendor/*/ 10 | 11 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 12 | *.o 13 | *.a 14 | *.so 15 | 16 | # Folders 17 | _obj 18 | _test 19 | 20 | # Architecture specific extensions/prefixes 21 | *.[568vq] 22 | [568vq].out 23 | 24 | *.cgo1.go 25 | *.cgo2.c 26 | _cgo_defun.c 27 | _cgo_gotypes.go 28 | _cgo_export.* 29 | 30 | _testmain.go 31 | 32 | *.exe 33 | *.test 34 | *.prof 35 | -------------------------------------------------------------------------------- /form-fileupload/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

Example - Form File Upload

4 |

5 | 6 | This example illustrates aah form file upload. It is easy to handle file uploads in aah. It works by calling (method) `Req.SaveFile` with form field name and destination path. The method returns file size on successful save. 7 | 8 | ```go 9 | fileSize, err := Req.SaveFile("userProfileImage", "/Users/jeeva/user-profile-uploads") 10 | ``` 11 | 12 | ### Get aah examples 13 | 14 | ```bash 15 | git clone https://github.com/go-aah/examples.git aah-examples 16 | ``` 17 | 18 | ### Run this example 19 | 20 | ```bash 21 | cd aah-examples/form-fileupload 22 | aah run 23 | ``` 24 | 25 | ### Visit this URL 26 | 27 | * http://localhost:8080 28 | 29 | Home page includes the details of implemented functionality and has a button to choose file and upload. It is self explanatory. 30 | -------------------------------------------------------------------------------- /form-fileupload/app/controllers/app.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package controllers 6 | 7 | import ( 8 | "fmt" 9 | "path/filepath" 10 | "time" 11 | 12 | "aahframe.work" 13 | "aahframe.work/essentials" 14 | "aahframework.org/examples/form-fileupload/app/models" 15 | "aahframework.org/examples/form-fileupload/app/util" 16 | ) 17 | 18 | // AppController struct application controller 19 | type AppController struct { 20 | *aah.Context 21 | } 22 | 23 | // Index method is application home page. 24 | func (c *AppController) Index() { 25 | data := aah.Data{ 26 | "Greet": models.Greet{ 27 | Message: "Welcome to aah framework - File Upload Example", 28 | }, 29 | } 30 | 31 | c.Reply().Ok().HTML(data) 32 | } 33 | 34 | // FileUpload method is to save uploaded multipart into destination path. 35 | func (c *AppController) FileUpload(fileName string) { 36 | filename := fmt.Sprintf("%s-%s%s", 37 | ess.StripExt(fileName), 38 | time.Now().Format("2006-01-02-15-04-05"), 39 | filepath.Ext(fileName)) 40 | 41 | dstFile := filepath.Join(util.UploadsPath(), filename) 42 | 43 | // Using aah convenient methoed to save uploaded file 44 | size, err := c.Req.SaveFile("fileUpload", dstFile) 45 | if err != nil { 46 | c.Reply().HTML(aah.Data{ 47 | "IsError": true, 48 | }) 49 | return 50 | } 51 | 52 | c.Reply().HTML(aah.Data{ 53 | "SavedFileName": filepath.Base(dstFile), 54 | "FileSize": size, 55 | }) 56 | } 57 | -------------------------------------------------------------------------------- /form-fileupload/app/models/greet.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package models 6 | 7 | // Greet holds the greeting message. 8 | type Greet struct { 9 | Message string `json:"message"` 10 | } 11 | -------------------------------------------------------------------------------- /form-fileupload/app/util/util.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "path/filepath" 5 | 6 | "aahframe.work" 7 | "aahframe.work/essentials" 8 | "aahframe.work/log" 9 | ) 10 | 11 | func UploadsPath() string { 12 | return filepath.Join(aah.App().BaseDir(), "uploads") 13 | } 14 | 15 | func CreateUploadsDirectory(_ *aah.Event) { 16 | if err := ess.MkDirAll(UploadsPath(), 0766); err != nil { 17 | log.Error(err) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /form-fileupload/config/env/dev.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Development Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | dev { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Log Configuration 9 | # 10 | # Doc: https://docs.aahframework.org/logging.html 11 | # Doc: https://docs.aahframework.org/log-config.html 12 | # ----------------------------------------------------------------------------- 13 | log { 14 | receiver = "console" 15 | level = "debug" 16 | format = "text" 17 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 18 | color = true 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /form-fileupload/config/env/prod.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Production Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | prod { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Runtime configuration 9 | # Doc: https://docs.aahframework.org/app-config.html#section-runtime 10 | # ----------------------------------------------------------------------------- 11 | runtime { 12 | debug { 13 | strip_src_base = true 14 | } 15 | } 16 | 17 | # ----------------------------------------------------------------------------- 18 | # Log Configuration 19 | # 20 | # Doc: https://docs.aahframework.org/logging.html 21 | # Doc: https://docs.aahframework.org/log-config.html 22 | # ----------------------------------------------------------------------------- 23 | log { 24 | receiver = "file" 25 | file = "form-fileupload.log" 26 | level = "warn" 27 | format = "text" 28 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 29 | color = false 30 | rotate { 31 | policy = "daily" 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /form-fileupload/config/routes.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # form-fileupload - Application Routes Configuration 3 | # 4 | # Refer documentation to explore and configure routes. 5 | # Doc: https://docs.aahframework.org/routing.html 6 | # ----------------------------------------------------------------------------- 7 | 8 | domains { 9 | #------------------------------------------------------------------------------ 10 | # Domain/subdomain Key Name 11 | # Choose an `unique keyname` to define domain section and its configuration. 12 | # Tip: domain name address, port no values to create a domain key, etc. 13 | # 14 | # Doc: https://docs.aahframework.org/routes-config.html#domain-configuration 15 | #------------------------------------------------------------------------------ 16 | localhost { 17 | name = "form-fileupload routes" 18 | host = "localhost" 19 | 20 | #------------------------------------------------------------------------------ 21 | # Static files Routes Configuration 22 | # To serve static files, it can be directory or individual file. 23 | # This section optional one, for e.g: RESTful APIs doesn't need this section. 24 | # Static files are delivered via `http.ServeContent`. 25 | # 26 | # Supported features: 27 | # - Serve directory 28 | # - Serve individual file 29 | # - Directory listing 30 | # 31 | # Choose an `unique name` for each `directory` or `individual` file 32 | # static route definition. It is called `route name`. 33 | # 34 | # Doc: https://docs.aahframework.org/routes-config.html#section-static 35 | #------------------------------------------------------------------------------ 36 | static { 37 | public_assets { 38 | path = "/static" 39 | dir = "static" 40 | } 41 | 42 | favicon { 43 | path = "/favicon.ico" 44 | file = "img/favicon.ico" 45 | } 46 | 47 | robots_txt { 48 | path = "/robots.txt" 49 | file = "robots.txt" 50 | } 51 | } 52 | 53 | # ----------------------------------------------------------------------------- 54 | # Routes Configuration 55 | # 56 | # Doc: https://docs.aahframework.org/routes-config.html#routes-configuration 57 | # ----------------------------------------------------------------------------- 58 | routes { 59 | index { 60 | path = "/" 61 | controller = "AppController" 62 | } 63 | 64 | file_upload { 65 | path = "/file-upload" 66 | method = "POST" 67 | controller = "AppController" 68 | action = "FileUpload" 69 | max_body_size = "12mb" 70 | } 71 | 72 | } # end - routes 73 | 74 | } # end - localhost 75 | 76 | } # end - domains 77 | -------------------------------------------------------------------------------- /form-fileupload/config/security.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # form-fileupload - Application Security Configuration 3 | # 4 | # Refer documentation to explore and customize the configurations. 5 | # Doc: https://docs.aahframework.org/security-config.html 6 | # ----------------------------------------------------------------------------- 7 | 8 | security { 9 | # --------------------------------------------------------------------------- 10 | # HTTP Secure Header(s) 11 | # Application security headers with many safe defaults. 12 | # 13 | # Doc: https://docs.aahframework.org/security-config.html#section-http-header 14 | # 15 | # Tip: Quick way to verify secure headers - https://securityheaders.io 16 | # --------------------------------------------------------------------------- 17 | http_header { 18 | enable = true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /form-fileupload/go.mod: -------------------------------------------------------------------------------- 1 | module aahframework.org/examples/form-fileupload 2 | 3 | require ( 4 | aahframe.work v0.12.2 5 | aahframe.work/minify/html v0.2.0 6 | ) 7 | -------------------------------------------------------------------------------- /form-fileupload/i18n/messages.en: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for form-fileupload application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | # This structure is example purpose 8 | # So choose your suitable structure for your application 9 | label { 10 | pages { 11 | app { 12 | index { 13 | title = "File Upload Example - Home | aah Go web framework" 14 | } 15 | 16 | fileupload { 17 | title = "File uploaded successfully - File Upload Example | aah Go web framework" 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /form-fileupload/static/css/aah.css: -------------------------------------------------------------------------------- 1 | /* 2 | Minimal aah framework application template CSS. 3 | Based on your need choose your CSS framework. 4 | */ 5 | 6 | .welcome-msg { 7 | padding-top: 30px; 8 | padding-bottom: 30px; 9 | color: inherit; 10 | } 11 | 12 | .desc-box { 13 | width: 70%; 14 | } 15 | 16 | .upload-form-box { 17 | margin-left: 40%; 18 | margin-top: 2%; 19 | width: 70%; 20 | } 21 | 22 | #filenameDisplay { 23 | margin-top: 5%; 24 | font-weight: bold; 25 | } 26 | 27 | #fileUpload { 28 | display: none !important; 29 | } 30 | 31 | .fileupload-success { 32 | margin-left: 20%; 33 | margin-top: 4%; 34 | width: 60%; 35 | } 36 | 37 | .tip-box { 38 | width: 70%; 39 | margin-top: 4%; 40 | } 41 | 42 | .tip-box .alert-success { 43 | padding-left: 10%; 44 | } 45 | 46 | [hidden] { 47 | display: none !important; 48 | } 49 | -------------------------------------------------------------------------------- /form-fileupload/static/img/aah-framework-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/form-fileupload/static/img/aah-framework-logo.png -------------------------------------------------------------------------------- /form-fileupload/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/form-fileupload/static/img/favicon.ico -------------------------------------------------------------------------------- /form-fileupload/static/js/aah.js: -------------------------------------------------------------------------------- 1 | // JS file 2 | 3 | function showFilename() { 4 | var filePath = document.getElementById('fileUpload').value 5 | if (filePath) { 6 | if (filePath.indexOf('\\')) { 7 | filePath = filePath.substring(filePath.lastIndexOf('\\')) 8 | } else if (filePath.indexOf('/')) { 9 | filePath = filePath.substring(filePath.lastIndexOf('/')) 10 | } 11 | 12 | var chr = filePath.charAt(0); 13 | if (chr === '\\' || chr === '/') { 14 | filePath = filePath.substring(1); 15 | } 16 | 17 | document.getElementById('filenameDisplay').innerHTML = filePath; 18 | document.getElementById('fileName').value = filePath; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /form-fileupload/static/robots.txt: -------------------------------------------------------------------------------- 1 | # Prevents all robots visiting your site. 2 | User-agent: * 3 | Disallow: / 4 | -------------------------------------------------------------------------------- /form-fileupload/views/common/error_footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /form-fileupload/views/common/error_header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ .Error.Code }} {{ .Error.Message }} 8 | 9 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /form-fileupload/views/common/footer_scripts.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /form-fileupload/views/common/head_tags.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /form-fileupload/views/errors/404.html: -------------------------------------------------------------------------------- 1 | {{ include "/common/error_header.html" . -}} 2 |
{{ with .Error }} 3 |
4 |
5 | {{ .Code }} {{ .Message }} 6 |
7 |
{{ end }} 8 |
9 | {{ include "/common/error_footer.html" . -}} 10 | -------------------------------------------------------------------------------- /form-fileupload/views/errors/500.html: -------------------------------------------------------------------------------- 1 | {{ include "/common/error_header.html" . -}} 2 |
{{ with .Error }} 3 |
4 |
5 | {{ .Code }} {{ .Message }} 6 |
7 |
{{ end }} 8 |
9 | {{ include "/common/error_footer.html" . -}} 10 | -------------------------------------------------------------------------------- /form-fileupload/views/layouts/master.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ template "title" . }} 8 | {{ include "/common/head_tags.html" . }} 9 | 10 | 11 | {{ template "body" . -}} 12 | {{ include "/common/footer_scripts.html" . }} 13 | 14 | 15 | -------------------------------------------------------------------------------- /form-fileupload/views/pages/app/fileupload.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | {{ i18n . "label.pages.app.fileupload.title" }} 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 |
7 |
8 |
9 |
10 | {{ if .IsError }} 11 |
12 |

Error occurred while uploading file

13 |
14 | {{ else }} 15 |
16 | File have been uploaded successfully 17 |
18 |
19 |
20 |
Request File Name:
21 |
{{ fparam . "fileName" }}
22 |
Saved File Name:
23 |
{{ .SavedFileName }}
24 |
File Size:
25 |
{{ .FileSize }} bytes
26 |
27 | {{ end }} 28 |
29 |
30 |
31 |

Example upload location: <app-base-dir>/uploads

32 |

33 | Go to Home 34 |
35 |
36 |
37 | {{- end }} 38 | -------------------------------------------------------------------------------- /form-fileupload/views/pages/app/index.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | {{ i18n . "label.pages.app.index.title" }} 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 |
7 |
8 |
9 | aah framework logo 10 |

{{ .Greet.Message }}

11 |
12 | 13 |
14 |
15 |

Mutlipart File upload handling in aah framework is very easy. Design your form as you wish, choose name of the form file field and submit the form.

16 |

On server side just call method Req.SaveFile with form field name and destination path. That's it! 17 |

18 |
19 |
20 |
21 |
22 |
23 | 24 |
25 |
26 |
27 | 30 | 31 | 32 |
33 |
34 |
35 | 36 |
37 |
38 |
39 |

Tip: 40 |

    41 |
  • Example upload location: <app-base-dir>/uploads.
  • 42 |
  • Method SaveFile returns file size on successful save.
  • 43 |
44 |

45 |
46 |
47 |
48 |
49 |
50 | {{- end }} 51 | -------------------------------------------------------------------------------- /form/.gitignore: -------------------------------------------------------------------------------- 1 | # aah framework application - .gitignore 2 | 3 | aah.go 4 | *.pid 5 | build/ 6 | aah_*_vfs.go 7 | app/generated 8 | vendor/*/ 9 | # aah application - end 10 | 11 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 12 | *.o 13 | *.a 14 | *.so 15 | 16 | # Folders 17 | _obj 18 | _test 19 | 20 | # Architecture specific extensions/prefixes 21 | *.[568vq] 22 | [568vq].out 23 | 24 | *.cgo1.go 25 | *.cgo2.c 26 | _cgo_defun.c 27 | _cgo_gotypes.go 28 | _cgo_export.* 29 | 30 | _testmain.go 31 | 32 | *.exe 33 | *.test 34 | *.prof 35 | -------------------------------------------------------------------------------- /form/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

Example - Form Submission

4 |

5 | 6 | This example demonstrates how form submission happens in aah framework. Form submission includes auto parse and bind (nested struct bind and input sanitization to prevent XSS attacks). Take a moment to learn about the clean and robust implementation of [auto parse and bind](https://docs.aahframework.org/request-parameters-auto-bind.html) capabilities. 7 | 8 | ### Get aah examples 9 | 10 | ```bash 11 | git clone https://github.com/go-aah/examples.git aah-examples 12 | ``` 13 | 14 | ### Run this example 15 | 16 | ```bash 17 | cd aah-examples/form 18 | aah run 19 | ``` 20 | 21 | ### Visit this URL 22 | 23 | * http://localhost:8080 24 | 25 | Home page includes the details of implemented functionality and button to access User Profile - Form Submission. Fill out the form fields and click submit. As a response, the submitted field values will be displayed on the page. 26 | -------------------------------------------------------------------------------- /form/app/controllers/app.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package controllers 6 | 7 | import ( 8 | "html" 9 | "html/template" 10 | 11 | "aahframe.work" 12 | "aahframework.org/examples/form/app/models" 13 | ) 14 | 15 | // AppController struct application controller 16 | type AppController struct { 17 | *aah.Context 18 | } 19 | 20 | // Index method is application home page. 21 | func (c *AppController) Index() { 22 | data := aah.Data{ 23 | "Greet": models.Greet{ 24 | Message: "Welcome to aah framework - Form Submission Example", 25 | }, 26 | } 27 | 28 | c.Reply().Ok().HTML(data) 29 | } 30 | 31 | // UserProfile method displays the user profile info page. 32 | func (c *AppController) UserProfile() { 33 | c.Reply().Ok() 34 | } 35 | 36 | // UserProfileSubmit method receives Form submission 37 | func (c *AppController) UserProfileSubmit(user *models.User) { 38 | c.Reply().HTMLf("userprofile.html", aah.Data{ 39 | "DataDisplay": true, 40 | "User": user, 41 | "AboutYou": template.HTML(html.UnescapeString(user.AboutYou)), 42 | }) 43 | } 44 | -------------------------------------------------------------------------------- /form/app/models/greet.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package models 6 | 7 | // Greet holds the greeting message. 8 | type Greet struct { 9 | Message string `json:"message"` 10 | } 11 | -------------------------------------------------------------------------------- /form/app/models/user.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package models 6 | 7 | // User struct holds user profile info 8 | type User struct { 9 | FirstName string `bind:"first_name"` 10 | LastName string `bind:"last_name"` 11 | Email string `bind:"email"` 12 | AboutYou string `bind:"about_you"` 13 | Residence *Address `bind:"residence"` 14 | } 15 | 16 | // Address struct holds address information 17 | type Address struct { 18 | Address1 string `bind:"address1"` 19 | Address2 string `bind:"address2"` 20 | City string `bind:"city"` 21 | ZipCode string `bind:"zip_code"` 22 | } 23 | -------------------------------------------------------------------------------- /form/config/env/dev.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Development Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | dev { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Log Configuration 9 | # 10 | # Doc: https://docs.aahframework.org/logging.html 11 | # Doc: https://docs.aahframework.org/log-config.html 12 | # ----------------------------------------------------------------------------- 13 | log { 14 | receiver = "console" 15 | level = "debug" 16 | format = "text" 17 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 18 | color = true 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /form/config/env/prod.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Production Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | prod { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Runtime configuration 9 | # Doc: https://docs.aahframework.org/app-config.html#section-runtime 10 | # ----------------------------------------------------------------------------- 11 | runtime { 12 | debug { 13 | strip_src_base = true 14 | } 15 | } 16 | 17 | # ----------------------------------------------------------------------------- 18 | # Log Configuration 19 | # 20 | # Doc: https://docs.aahframework.org/logging.html 21 | # Doc: https://docs.aahframework.org/log-config.html 22 | # ----------------------------------------------------------------------------- 23 | log { 24 | receiver = "file" 25 | file = "form.log" 26 | level = "warn" 27 | format = "text" 28 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 29 | color = false 30 | rotate { 31 | policy = "daily" 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /form/config/routes.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # form - Application Routes Configuration 3 | # 4 | # Refer documentation to explore and configure routes. 5 | # Doc: https://docs.aahframework.org/routing.html 6 | # ----------------------------------------------------------------------------- 7 | 8 | domains { 9 | #------------------------------------------------------------------------------ 10 | # Domain/subdomain Key Name 11 | # Choose an `unique keyname` to define domain section and its configuration. 12 | # Tip: domain name address, port no values to create a domain key, etc. 13 | # 14 | # Doc: https://docs.aahframework.org/routes-config.html#domain-configuration 15 | #------------------------------------------------------------------------------ 16 | localhost { 17 | name = "form routes" 18 | host = "localhost" 19 | 20 | #------------------------------------------------------------------------------ 21 | # Static files Routes Configuration 22 | # To serve static files, it can be directory or individual file. 23 | # This section optional one, for e.g: RESTful APIs doesn't need this section. 24 | # Static files are delivered via `http.ServeContent`. 25 | # 26 | # Supported features: 27 | # - Serve directory 28 | # - Serve individual file 29 | # - Directory listing 30 | # 31 | # Choose an `unique name` for each `directory` or `individual` file 32 | # static route definition. It is called `route name`. 33 | # 34 | # Doc: https://docs.aahframework.org/routes-config.html#section-static 35 | #------------------------------------------------------------------------------ 36 | static { 37 | public_assets { 38 | path = "/static" 39 | dir = "static" 40 | } 41 | 42 | favicon { 43 | path = "/favicon.ico" 44 | file = "img/favicon.ico" 45 | } 46 | 47 | robots_txt { 48 | path = "/robots.txt" 49 | file = "robots.txt" 50 | } 51 | } 52 | 53 | # ----------------------------------------------------------------------------- 54 | # Routes Configuration 55 | # 56 | # Doc: https://docs.aahframework.org/routes-config.html#routes-configuration 57 | # ----------------------------------------------------------------------------- 58 | routes { 59 | index { 60 | path = "/" 61 | controller = "AppController" 62 | } 63 | 64 | user_profile { 65 | path = "/user/profile.html" 66 | controller = "AppController" 67 | action = "UserProfile" 68 | } 69 | 70 | user_profile_submit { 71 | path = "/user/profile.html" 72 | method = "POST" 73 | controller = "AppController" 74 | action = "UserProfileSubmit" 75 | } 76 | 77 | } # end - routes 78 | 79 | } # end - localhost 80 | 81 | } # end - domains 82 | -------------------------------------------------------------------------------- /form/config/security.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # form - Application Security Configuration 3 | # 4 | # Refer documentation to explore and customize the configurations. 5 | # Doc: https://docs.aahframework.org/security-config.html 6 | # ----------------------------------------------------------------------------- 7 | 8 | security { 9 | # --------------------------------------------------------------------------- 10 | # HTTP Secure Header(s) 11 | # Application security headers with many safe defaults. 12 | # 13 | # Doc: https://docs.aahframework.org/security-config.html#section-http-header 14 | # 15 | # Tip: Quick way to verify secure headers - https://securityheaders.io 16 | # --------------------------------------------------------------------------- 17 | http_header { 18 | enable = true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /form/go.mod: -------------------------------------------------------------------------------- 1 | module aahframework.org/examples/form 2 | 3 | require ( 4 | aahframe.work v0.12.2 5 | aahframe.work/minify/html v0.2.0 6 | ) 7 | -------------------------------------------------------------------------------- /form/i18n/messages.en: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for form application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | # This structure is example purpose 8 | # So choose your suitable structure for your application 9 | 10 | label { 11 | pages { 12 | app { 13 | index { 14 | title = "Form Submission Example - Welcome to aah Go web framework" 15 | } 16 | 17 | user_profile { 18 | title = "User Profile - Form Submission Example | aah Go web framework" 19 | 20 | form { 21 | first_name = "First Name" 22 | last_name = "Last Name" 23 | email = "Email Address" 24 | about_you = "About you" 25 | } 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /form/static/css/aah.css: -------------------------------------------------------------------------------- 1 | /* 2 | Minimal aah framework application template CSS. 3 | Based on your need choose your CSS framework. 4 | */ 5 | 6 | .welcome-msg { 7 | padding-top: 30px; 8 | padding-bottom: 30px; 9 | color: inherit; 10 | } 11 | 12 | #submit-btn { 13 | margin-top:3%; 14 | } 15 | 16 | .user-profile-form { 17 | width: 65%; 18 | margin-top: 2%; 19 | margin-left: 20%; 20 | } 21 | 22 | fieldset { 23 | border: 1px solid #ddd !important; 24 | margin: 0; 25 | xmin-width: 0; 26 | width: 100% !important; 27 | padding: 10px; 28 | position: relative; 29 | border-radius:4px; 30 | padding-left:10px!important; 31 | } 32 | 33 | legend { 34 | font-size:14px; 35 | font-weight:bold; 36 | margin-bottom: 0px; 37 | border: 0; 38 | width: 23%; 39 | padding: 5px 5px 5px 10px; 40 | } 41 | 42 | .form-btn { 43 | margin-top: 30px; 44 | } 45 | 46 | .user-profile-form .dl-horizontal dd { 47 | margin-left: 200px; 48 | } 49 | 50 | .user-profile-form .dl-horizontal dt { 51 | float: left; 52 | width: 180px; 53 | } 54 | -------------------------------------------------------------------------------- /form/static/img/aah-framework-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/form/static/img/aah-framework-logo.png -------------------------------------------------------------------------------- /form/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/form/static/img/favicon.ico -------------------------------------------------------------------------------- /form/static/js/aah.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/form/static/js/aah.js -------------------------------------------------------------------------------- /form/static/robots.txt: -------------------------------------------------------------------------------- 1 | # Prevents all robots visiting your site. 2 | User-agent: * 3 | Disallow: / 4 | -------------------------------------------------------------------------------- /form/views/common/error_footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /form/views/common/error_header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ .Error.Code }} {{ .Error.Message }} 8 | 9 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /form/views/common/footer_scripts.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /form/views/common/head_tags.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /form/views/errors/404.html: -------------------------------------------------------------------------------- 1 | {{ include "/common/error_header.html" . -}} 2 |
{{ with .Error }} 3 |
4 |
5 | {{ .Code }} {{ .Message }} 6 |
7 |
{{ end }} 8 |
9 | {{ include "/common/error_footer.html" . -}} 10 | -------------------------------------------------------------------------------- /form/views/errors/500.html: -------------------------------------------------------------------------------- 1 | {{ include "/common/error_header.html" . -}} 2 |
{{ with .Error }} 3 |
4 |
5 | {{ .Code }} {{ .Message }} 6 |
7 |
{{ end }} 8 |
9 | {{ include "/common/error_footer.html" . -}} 10 | -------------------------------------------------------------------------------- /form/views/layouts/master.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ template "title" . }} 8 | {{ include "/common/head_tags.html" . }} 9 | 10 | 11 | {{ template "body" . -}} 12 | {{ include "/common/footer_scripts.html" . }} 13 | 14 | 15 | -------------------------------------------------------------------------------- /form/views/pages/app/index.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | {{ i18n . "label.pages.app.index.title" }} 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 |
7 |
8 |
9 | aah framework logo 10 |

{{ .Greet.Message }}

11 |
12 | 13 |
14 |
15 |

This sample application demostrates following:

16 |

17 |

    18 |
  • Auto Parse and Bind
  • 19 |
    • 20 |
    • Form Submission
    • 21 |
    • Bind with Nested Struct
    • 22 |
    • Input Sanitization
    • 23 |
  • 24 |
  • If you would like to do manual parsing (this is not Sanitized values)
  • 25 |
    • 26 |
    • Use ctx.Req.FormValue and ctx.Req.FormArrayValue
    • 27 |
  • 28 |
29 |

30 |
31 |
32 | 33 |
34 |

Click here to Submit User Profile Form

35 |
36 | 37 |
38 |
39 | {{- end }} 40 | -------------------------------------------------------------------------------- /i18n-url-path-param/.gitignore: -------------------------------------------------------------------------------- 1 | # aah framework application - .gitignore 2 | 3 | aah.go 4 | *.pid 5 | build/ 6 | aah_*_vfs.go 7 | app/generated 8 | vendor/*/ 9 | # aah application - end 10 | 11 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 12 | *.o 13 | *.a 14 | *.so 15 | 16 | # Folders 17 | _obj 18 | _test 19 | 20 | # Architecture specific extensions/prefixes 21 | *.[568vq] 22 | [568vq].out 23 | 24 | *.cgo1.go 25 | *.cgo2.c 26 | _cgo_defun.c 27 | _cgo_gotypes.go 28 | _cgo_export.* 29 | 30 | _testmain.go 31 | 32 | *.exe 33 | *.test 34 | *.prof 35 | -------------------------------------------------------------------------------- /i18n-url-path-param/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

Example - i18n URL Path Parameter

4 |

5 | 6 | This example demonstrates i18n - Internationalization with aah framework using **URL Path Parameter**. By applying aah configuration and convention, zero coding effort can be achieved on this aspect. 7 | 8 | Application has below route URL pattern - 9 | 10 | ``` 11 | /page/:language/index.html 12 | ``` 13 | 14 | Learn how i18n works in aah - https://docs.aahframework.org/i18n.html. 15 | 16 | ### Get aah examples 17 | 18 | ```bash 19 | git clone https://github.com/go-aah/examples.git aah-examples 20 | ``` 21 | 22 | ### Run this example 23 | 24 | ```bash 25 | cd aah-examples/i18n-url-path-param 26 | aah run 27 | ``` 28 | 29 | ### Visit this URL 30 | 31 | Go to home page, click on language links to see i18n in action. 32 | 33 | * Home page : http://localhost:8080 34 | 35 | Localized URLs: 36 | 37 | - http://localhost:8080/page/en/index.html 38 | - http://localhost:8080/page/zh-CN/index.html 39 | - http://localhost:8080/page/ja/index.html 40 | - http://localhost:8080/page/es-ES/index.html 41 | - http://localhost:8080/page/es-MX/index.html 42 | - http://localhost:8080/page/de-DE/index.html 43 | 44 | -------------------------------------------------------------------------------- /i18n-url-path-param/app/controllers/app.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package controllers 6 | 7 | import "aahframe.work" 8 | 9 | // AppController struct application controller 10 | type AppController struct { 11 | *aah.Context 12 | } 13 | 14 | // Index method is to redirect root directory to locaized page. 15 | func (c *AppController) Index() { 16 | c.Reply().Redirect(c.RouteURL("index_lang", "en")) 17 | } 18 | 19 | // IndexLang method is application home page. 20 | func (c *AppController) IndexLang() { 21 | c.Reply().Ok().HTMLf("index.html", nil) 22 | } 23 | -------------------------------------------------------------------------------- /i18n-url-path-param/config/env/dev.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Development Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | dev { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Log Configuration 9 | # 10 | # Doc: https://docs.aahframework.org/logging.html 11 | # Doc: https://docs.aahframework.org/log-config.html 12 | # ----------------------------------------------------------------------------- 13 | log { 14 | receiver = "console" 15 | level = "debug" 16 | format = "text" 17 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 18 | color = true 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /i18n-url-path-param/config/env/prod.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Production Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | prod { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Runtime configuration 9 | # Doc: https://docs.aahframework.org/app-config.html#section-runtime 10 | # ----------------------------------------------------------------------------- 11 | runtime { 12 | debug { 13 | strip_src_base = true 14 | } 15 | } 16 | 17 | # ----------------------------------------------------------------------------- 18 | # Log Configuration 19 | # 20 | # Doc: https://docs.aahframework.org/logging.html 21 | # Doc: https://docs.aahframework.org/log-config.html 22 | # ----------------------------------------------------------------------------- 23 | log { 24 | receiver = "file" 25 | file = "i18n-url-path-param.log" 26 | level = "warn" 27 | format = "text" 28 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 29 | color = false 30 | rotate { 31 | policy = "daily" 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /i18n-url-path-param/config/routes.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # i18n-url-path-param - Application Routes Configuration 3 | # 4 | # Refer documentation to explore and configure routes. 5 | # Doc: https://docs.aahframework.org/routing.html 6 | # ----------------------------------------------------------------------------- 7 | 8 | domains { 9 | #------------------------------------------------------------------------------ 10 | # Domain/subdomain Key Name 11 | # Choose an `unique keyname` to define domain section and its configuration. 12 | # Tip: domain name address, port no values to create a domain key, etc. 13 | # 14 | # Doc: https://docs.aahframework.org/routes-config.html#domain-configuration 15 | #------------------------------------------------------------------------------ 16 | localhost { 17 | name = "i18n routes" 18 | host = "localhost" 19 | 20 | #------------------------------------------------------------------------------ 21 | # Static files Routes Configuration 22 | # To serve static files, it can be directory or individual file. 23 | # This section optional one, for e.g: RESTful APIs doesn't need this section. 24 | # Static files are delivered via `http.ServeContent`. 25 | # 26 | # Supported features: 27 | # - Serve directory 28 | # - Serve individual file 29 | # - Directory listing 30 | # 31 | # Choose an `unique name` for each `directory` or `individual` file 32 | # static route definition. It is called `route name`. 33 | # 34 | # Doc: https://docs.aahframework.org/routes-config.html#section-static 35 | #------------------------------------------------------------------------------ 36 | static { 37 | public_assets { 38 | path = "/static" 39 | dir = "static" 40 | } 41 | 42 | favicon { 43 | path = "/favicon.ico" 44 | file = "img/favicon.ico" 45 | } 46 | 47 | robots_txt { 48 | path = "/robots.txt" 49 | file = "robots.txt" 50 | } 51 | } 52 | 53 | # ----------------------------------------------------------------------------- 54 | # Routes Configuration 55 | # 56 | # Doc: https://docs.aahframework.org/routes-config.html#routes-configuration 57 | # ----------------------------------------------------------------------------- 58 | routes { 59 | index { 60 | path = "/" 61 | controller = "AppController" 62 | } 63 | 64 | index_lang { 65 | path = "/page/:lang/index.html" 66 | controller = "AppController" 67 | action = "IndexLang" 68 | } 69 | 70 | } # end - routes 71 | 72 | } # end - localhost 73 | 74 | } # end - domains 75 | -------------------------------------------------------------------------------- /i18n-url-path-param/config/security.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # i18n-url-path-param - Application Security Configuration 3 | # 4 | # Refer documentation to explore and customize the configurations. 5 | # Doc: https://docs.aahframework.org/security-config.html 6 | # ----------------------------------------------------------------------------- 7 | 8 | security { 9 | 10 | # --------------------------------------------------------------------------- 11 | # HTTP Secure Header(s) 12 | # Application security headers with many safe defaults. 13 | # 14 | # Doc: https://docs.aahframework.org/security-config.html#section-http-header 15 | # 16 | # Tip: Quick way to verify secure headers - https://securityheaders.io 17 | # --------------------------------------------------------------------------- 18 | http_header { 19 | enable = true 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /i18n-url-path-param/go.mod: -------------------------------------------------------------------------------- 1 | module aahframework.org/examples/i18n-url-path-param 2 | 3 | require ( 4 | aahframe.work v0.12.2 5 | aahframe.work/minify/html v0.2.0 6 | ) 7 | -------------------------------------------------------------------------------- /i18n-url-path-param/i18n/messages.de-DE: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for i18n-url-path-param application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | page { 8 | app { 9 | index { 10 | title = "Example - i18n | Aah Web-Framework für Go" 11 | welcome_text = "Willkommen bei aah Framework - Web Application" 12 | notes = "Sie können Internationalisierung und Lokalisierung durch Anwendung von Aah-Konfiguration und Konvention erreichen. Zero Coding-Aufwand! Das ist schön." 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /i18n-url-path-param/i18n/messages.en: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for i18n-url-path-param application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | page { 8 | app { 9 | index { 10 | title = "Example - i18n | aah Go web framework for Go" 11 | welcome_text = "Welcome to aah framework - Web Application" 12 | notes = "You can achieve Internationalization and Localization by applying aah configuration and convention. Zero coding effort! That's Nice." 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /i18n-url-path-param/i18n/messages.es-ES: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for i18n-url-path-param application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | page { 8 | app { 9 | index { 10 | title = "Example - i18n | aah Go web framework para Go" 11 | welcome_text = "Bienvenido a aah framework - Aplicación Web" 12 | notes = "Puede lograr la internacionalización y la localización aplicando una configuración y una convención de aah. Cero esfuerzo de codificación! Eso es bueno." 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /i18n-url-path-param/i18n/messages.es-MX: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for i18n-url-path-param application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | page { 8 | app { 9 | index { 10 | title = "Example - i18n | AAH el framework web para ir" 11 | welcome_text = "Bienvenido a aah marco - aplicación Web" 12 | notes = "Puede lograr la internacionalización y la localización aplicando una configuración y una convención de aah. Cero esfuerzo de codificación! Eso es bueno." 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /i18n-url-path-param/i18n/messages.ja: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for i18n-url-path-param application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | page { 8 | app { 9 | index { 10 | title = "チュートリアル - i18n | Go for aah Webフレームワーク" 11 | welcome_text = "aahフレームワークへようこそ - Webアプリケーション" 12 | notes = "国際化とローカリゼーションを実現するには、aaの設定と規約を適用します。 ゼロコーディングの努力! それはすばらしい。" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /i18n-url-path-param/i18n/messages.zh-CN: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for i18n-url-path-param application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | page { 8 | app { 9 | index { 10 | title = "教程 - i18n | Go的aah网络框架" 11 | welcome_text = "欢迎来到aah框架 - Web应用程序" 12 | notes = "您可以通过应用aah配置和约定来实现国际化和本地化。 零编码工作! 这很好。" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /i18n-url-path-param/static/css/aah.css: -------------------------------------------------------------------------------- 1 | /* 2 | Minimal aah framework application template CSS. 3 | Based on your need choose your CSS framework. 4 | */ 5 | 6 | html { 7 | font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; 8 | -webkit-text-size-adjust: 100%; 9 | -ms-text-size-adjust: 100%; 10 | } 11 | 12 | body { 13 | margin: 0; 14 | } 15 | 16 | .container { 17 | padding-right: 15px; 18 | padding-left: 15px; 19 | margin-right: auto; 20 | margin-left: auto; 21 | } 22 | @media (min-width: 992px) { 23 | .container { 24 | width: 970px; 25 | } 26 | } 27 | @media (min-width: 1200px) { 28 | .container { 29 | width: 1170px; 30 | } 31 | } 32 | 33 | .row { 34 | margin-right: -15px; 35 | margin-left: -15px; 36 | } 37 | 38 | .text-center { 39 | text-align: center; 40 | } 41 | 42 | .welcome-msg { 43 | padding-top: 30px; 44 | padding-bottom: 30px; 45 | margin-bottom: 30px; 46 | color: inherit; 47 | } 48 | 49 | .text-muted { 50 | font-size: 12px; 51 | color: #757373; 52 | } 53 | 54 | .goal { 55 | font-size: 14px; 56 | color: #484747; 57 | } 58 | 59 | .lang-links { 60 | margin-bottom: 50px; 61 | } 62 | 63 | .lang-links a { 64 | text-decoration: none; 65 | color: inherit; 66 | } 67 | 68 | .lang-links a:hover { 69 | text-decoration: underline; 70 | color: #0045b5; 71 | } 72 | -------------------------------------------------------------------------------- /i18n-url-path-param/static/img/aah-framework-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/i18n-url-path-param/static/img/aah-framework-logo.png -------------------------------------------------------------------------------- /i18n-url-path-param/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/i18n-url-path-param/static/img/favicon.ico -------------------------------------------------------------------------------- /i18n-url-path-param/static/js/aah.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/i18n-url-path-param/static/js/aah.js -------------------------------------------------------------------------------- /i18n-url-path-param/static/robots.txt: -------------------------------------------------------------------------------- 1 | # Prevents all robots visiting your site. 2 | User-agent: * 3 | Disallow: / 4 | -------------------------------------------------------------------------------- /i18n-url-path-param/views/common/error_footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /i18n-url-path-param/views/common/error_header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ .Error.Code }} {{ .Error.Message }} 8 | 9 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /i18n-url-path-param/views/common/footer_scripts.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /i18n-url-path-param/views/common/head_tags.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /i18n-url-path-param/views/errors/404.html: -------------------------------------------------------------------------------- 1 | {{ include "/common/error_header.html" . -}} 2 |
{{ with .Error }} 3 |
4 |
5 | {{ .Code }} {{ .Message }} 6 |
7 |
{{ end }} 8 |
9 | {{ include "/common/error_footer.html" . -}} 10 | -------------------------------------------------------------------------------- /i18n-url-path-param/views/errors/500.html: -------------------------------------------------------------------------------- 1 | {{ include "/common/error_header.html" . -}} 2 |
{{ with .Error }} 3 |
4 |
5 | {{ .Code }} {{ .Message }} 6 |
7 |
{{ end }} 8 |
9 | {{ include "/common/error_footer.html" . -}} 10 | -------------------------------------------------------------------------------- /i18n-url-path-param/views/layouts/master.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ template "title" . }} 8 | {{ include "/common/head_tags.html" . }} 9 | 10 | 11 | {{ template "body" . -}} 12 | {{ include "/common/footer_scripts.html" . }} 13 | 14 | 15 | -------------------------------------------------------------------------------- /i18n-url-path-param/views/pages/app/index.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | {{ i18n . "page.app.index.title" }} 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 |
7 |
8 |
9 | 12 | Please note: Language listed here randomly to demostartion aah framework Internationalization (i18n) using URL Path Parameter, no specific order.
13 | Credit: Text translated using translate.google.com 14 |
15 |


16 | aah framework logo 17 |

{{ i18n . "page.app.index.welcome_text" }}

18 |

19 |
20 | {{ i18n . "page.app.index.notes" }} 21 |
22 |
23 |
24 | {{- end }} 25 | -------------------------------------------------------------------------------- /i18n-url-query-param/.gitignore: -------------------------------------------------------------------------------- 1 | # aah framework application - .gitignore 2 | 3 | aah.go 4 | *.pid 5 | build/ 6 | aah_*_vfs.go 7 | app/generated 8 | vendor/*/ 9 | # aah application - end 10 | 11 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 12 | *.o 13 | *.a 14 | *.so 15 | 16 | # Folders 17 | _obj 18 | _test 19 | 20 | # Architecture specific extensions/prefixes 21 | *.[568vq] 22 | [568vq].out 23 | 24 | *.cgo1.go 25 | *.cgo2.c 26 | _cgo_defun.c 27 | _cgo_gotypes.go 28 | _cgo_export.* 29 | 30 | _testmain.go 31 | 32 | *.exe 33 | *.test 34 | *.prof 35 | -------------------------------------------------------------------------------- /i18n-url-query-param/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

Example - i18n URL Query Parameter

4 |

5 | 6 | This example demonstrates i18n - Internationalization with aah framework using **URL Query Parameter**. By applying aah configuration and convention, zero coding effort can be achieved on this aspect. 7 | 8 | The application has below route URL pattern - 9 | 10 | ``` 11 | /?lang={language} 12 | ``` 13 | 14 | Learn how i18n works in aah - https://docs.aahframework.org/i18n.html. 15 | 16 | ### Get aah examples 17 | 18 | ```bash 19 | git clone https://github.com/go-aah/examples.git aah-examples 20 | ``` 21 | 22 | ### Run this example 23 | 24 | ```bash 25 | cd aah-examples/i18n-url-query-param 26 | aah run 27 | ``` 28 | 29 | ### Visit this URL 30 | 31 | Go to home page, click on language links to see i18n in action. 32 | 33 | * Home page : http://localhost:8080 34 | 35 | Localized URLs: 36 | 37 | - http://localhost:8080/?lang=en 38 | - http://localhost:8080/?lang=zh-CN 39 | - http://localhost:8080/?lang=ja 40 | - http://localhost:8080/?lang=es-ES 41 | - http://localhost:8080/?lang=es-MX 42 | - http://localhost:8080/?lang=de-DE 43 | 44 | -------------------------------------------------------------------------------- /i18n-url-query-param/app/controllers/app.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package controllers 6 | 7 | import "aahframe.work" 8 | 9 | // AppController struct application controller 10 | type AppController struct { 11 | *aah.Context 12 | } 13 | 14 | // Index method is application home page. 15 | func (c *AppController) Index() { 16 | c.Reply().Ok() 17 | } 18 | -------------------------------------------------------------------------------- /i18n-url-query-param/config/env/dev.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Development Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | dev { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Log Configuration 9 | # 10 | # Doc: https://docs.aahframework.org/logging.html 11 | # Doc: https://docs.aahframework.org/log-config.html 12 | # ----------------------------------------------------------------------------- 13 | log { 14 | receiver = "console" 15 | level = "debug" 16 | format = "text" 17 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 18 | color = true 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /i18n-url-query-param/config/env/prod.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Production Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | prod { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Runtime configuration 9 | # Doc: https://docs.aahframework.org/app-config.html#section-runtime 10 | # ----------------------------------------------------------------------------- 11 | runtime { 12 | debug { 13 | strip_src_base = true 14 | } 15 | } 16 | 17 | # ----------------------------------------------------------------------------- 18 | # Log Configuration 19 | # 20 | # Doc: https://docs.aahframework.org/logging.html 21 | # Doc: https://docs.aahframework.org/log-config.html 22 | # ----------------------------------------------------------------------------- 23 | log { 24 | receiver = "file" 25 | file = "i18n-url-query-param.log" 26 | level = "warn" 27 | format = "text" 28 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 29 | color = false 30 | rotate { 31 | policy = "daily" 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /i18n-url-query-param/config/routes.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # i18n-url-query-param - Application Routes Configuration 3 | # 4 | # Refer documentation to explore and configure routes. 5 | # Doc: https://docs.aahframework.org/routing.html 6 | # ----------------------------------------------------------------------------- 7 | 8 | domains { 9 | #------------------------------------------------------------------------------ 10 | # Domain/subdomain Key Name 11 | # Choose an `unique keyname` to define domain section and its configuration. 12 | # Tip: domain name address, port no values to create a domain key, etc. 13 | # 14 | # Doc: https://docs.aahframework.org/routes-config.html#domain-configuration 15 | #------------------------------------------------------------------------------ 16 | localhost { 17 | name = "i18n routes" 18 | host = "localhost" 19 | 20 | #------------------------------------------------------------------------------ 21 | # Static files Routes Configuration 22 | # To serve static files, it can be directory or individual file. 23 | # This section optional one, for e.g: RESTful APIs doesn't need this section. 24 | # Static files are delivered via `http.ServeContent`. 25 | # 26 | # Supported features: 27 | # - Serve directory 28 | # - Serve individual file 29 | # - Directory listing 30 | # 31 | # Choose an `unique name` for each `directory` or `individual` file 32 | # static route definition. It is called `route name`. 33 | # 34 | # Doc: https://docs.aahframework.org/routes-config.html#section-static 35 | #------------------------------------------------------------------------------ 36 | static { 37 | public_assets { 38 | path = "/static" 39 | dir = "static" 40 | } 41 | 42 | favicon { 43 | path = "/favicon.ico" 44 | file = "img/favicon.ico" 45 | } 46 | 47 | robots_txt { 48 | path = "/robots.txt" 49 | file = "robots.txt" 50 | } 51 | } 52 | 53 | # ----------------------------------------------------------------------------- 54 | # Routes Configuration 55 | # 56 | # Doc: https://docs.aahframework.org/routes-config.html#routes-configuration 57 | # ----------------------------------------------------------------------------- 58 | routes { 59 | index { 60 | path = "/" 61 | controller = "AppController" 62 | } 63 | 64 | } # end - routes 65 | 66 | } # end - localhost 67 | 68 | } # end - domains 69 | -------------------------------------------------------------------------------- /i18n-url-query-param/config/security.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # i18n-url-query-param - Application Security Configuration 3 | # 4 | # Refer documentation to explore and customize the configurations. 5 | # Doc: https://docs.aahframework.org/security-config.html 6 | # ----------------------------------------------------------------------------- 7 | 8 | security { 9 | 10 | # --------------------------------------------------------------------------- 11 | # HTTP Secure Header(s) 12 | # Application security headers with many safe defaults. 13 | # 14 | # Doc: https://docs.aahframework.org/security-config.html#section-http-header 15 | # 16 | # Tip: Quick way to verify secure headers - https://securityheaders.io 17 | # --------------------------------------------------------------------------- 18 | http_header { 19 | enable = true 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /i18n-url-query-param/go.mod: -------------------------------------------------------------------------------- 1 | module aahframework.org/examples/i18n-url-query-param 2 | 3 | require ( 4 | aahframe.work v0.12.2 5 | aahframe.work/minify/html v0.2.0 6 | ) 7 | -------------------------------------------------------------------------------- /i18n-url-query-param/i18n/messages.de-DE: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for i18n-url-query-param application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | page { 8 | app { 9 | index { 10 | title = "Example - i18n | Aah Web-Framework für Go" 11 | welcome_text = "Willkommen bei aah Framework - Web Application" 12 | notes = "Sie können Internationalisierung und Lokalisierung durch Anwendung von Aah-Konfiguration und Konvention erreichen. Zero Coding-Aufwand! Das ist schön." 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /i18n-url-query-param/i18n/messages.en: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for i18n-url-query-param application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | page { 8 | app { 9 | index { 10 | title = "Example - i18n | aah Go web framework for Go" 11 | welcome_text = "Welcome to aah framework - Web Application" 12 | notes = "You can achieve Internationalization and Localization by applying aah configuration and convention. Zero coding effort! That's Nice." 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /i18n-url-query-param/i18n/messages.es-ES: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for i18n-url-query-param application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | page { 8 | app { 9 | index { 10 | title = "Example - i18n | aah Go web framework para Go" 11 | welcome_text = "Bienvenido a aah framework - Aplicación Web" 12 | notes = "Puede lograr la internacionalización y la localización aplicando una configuración y una convención de aah. Cero esfuerzo de codificación! Eso es bueno." 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /i18n-url-query-param/i18n/messages.es-MX: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for i18n-url-query-param application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | page { 8 | app { 9 | index { 10 | title = "Example - i18n | AAH el framework web para ir" 11 | welcome_text = "Bienvenido a aah marco - aplicación Web" 12 | notes = "Puede lograr la internacionalización y la localización aplicando una configuración y una convención de aah. Cero esfuerzo de codificación! Eso es bueno." 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /i18n-url-query-param/i18n/messages.ja: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for i18n-url-query-param application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | page { 8 | app { 9 | index { 10 | title = "チュートリアル - i18n | Go for aah Webフレームワーク" 11 | welcome_text = "aahフレームワークへようこそ - Webアプリケーション" 12 | notes = "国際化とローカリゼーションを実現するには、aaの設定と規約を適用します。 ゼロコーディングの努力! それはすばらしい。" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /i18n-url-query-param/i18n/messages.zh-CN: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for i18n-url-query-param application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | page { 8 | app { 9 | index { 10 | title = "教程 - i18n | Go的aah网络框架" 11 | welcome_text = "欢迎来到aah框架 - Web应用程序" 12 | notes = "您可以通过应用aah配置和约定来实现国际化和本地化。 零编码工作! 这很好。" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /i18n-url-query-param/static/css/aah.css: -------------------------------------------------------------------------------- 1 | /* 2 | Minimal aah framework application template CSS. 3 | Based on your need choose your CSS framework. 4 | */ 5 | 6 | html { 7 | font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; 8 | -webkit-text-size-adjust: 100%; 9 | -ms-text-size-adjust: 100%; 10 | } 11 | 12 | body { 13 | margin: 0; 14 | } 15 | 16 | .container { 17 | padding-right: 15px; 18 | padding-left: 15px; 19 | margin-right: auto; 20 | margin-left: auto; 21 | } 22 | @media (min-width: 992px) { 23 | .container { 24 | width: 970px; 25 | } 26 | } 27 | @media (min-width: 1200px) { 28 | .container { 29 | width: 1170px; 30 | } 31 | } 32 | 33 | .row { 34 | margin-right: -15px; 35 | margin-left: -15px; 36 | } 37 | 38 | .text-center { 39 | text-align: center; 40 | } 41 | 42 | .welcome-msg { 43 | padding-top: 30px; 44 | padding-bottom: 30px; 45 | margin-bottom: 30px; 46 | color: inherit; 47 | } 48 | 49 | .text-muted { 50 | font-size: 12px; 51 | color: #757373; 52 | } 53 | 54 | .goal { 55 | font-size: 14px; 56 | color: #484747; 57 | } 58 | 59 | .lang-links { 60 | margin-bottom: 50px; 61 | } 62 | 63 | .lang-links a { 64 | text-decoration: none; 65 | color: inherit; 66 | } 67 | 68 | .lang-links a:hover { 69 | text-decoration: underline; 70 | color: #0045b5; 71 | } 72 | -------------------------------------------------------------------------------- /i18n-url-query-param/static/img/aah-framework-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/i18n-url-query-param/static/img/aah-framework-logo.png -------------------------------------------------------------------------------- /i18n-url-query-param/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/i18n-url-query-param/static/img/favicon.ico -------------------------------------------------------------------------------- /i18n-url-query-param/static/js/aah.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/i18n-url-query-param/static/js/aah.js -------------------------------------------------------------------------------- /i18n-url-query-param/static/robots.txt: -------------------------------------------------------------------------------- 1 | # Prevents all robots visiting your site. 2 | User-agent: * 3 | Disallow: / 4 | -------------------------------------------------------------------------------- /i18n-url-query-param/views/common/error_footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /i18n-url-query-param/views/common/error_header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ .Error.Code }} {{ .Error.Message }} 8 | 9 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /i18n-url-query-param/views/common/footer_scripts.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /i18n-url-query-param/views/common/head_tags.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /i18n-url-query-param/views/errors/404.html: -------------------------------------------------------------------------------- 1 | {{ include "/common/error_header.html" . -}} 2 |
{{ with .Error }} 3 |
4 |
5 | {{ .Code }} {{ .Message }} 6 |
7 |
{{ end }} 8 |
9 | {{ include "/common/error_footer.html" . -}} 10 | -------------------------------------------------------------------------------- /i18n-url-query-param/views/errors/500.html: -------------------------------------------------------------------------------- 1 | {{ include "/common/error_header.html" . -}} 2 |
{{ with .Error }} 3 |
4 |
5 | {{ .Code }} {{ .Message }} 6 |
7 |
{{ end }} 8 |
9 | {{ include "/common/error_footer.html" . -}} 10 | -------------------------------------------------------------------------------- /i18n-url-query-param/views/layouts/master.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ template "title" . }} 8 | {{ include "/common/head_tags.html" . }} 9 | 10 | 11 | {{ template "body" . -}} 12 | {{ include "/common/footer_scripts.html" . }} 13 | 14 | 15 | -------------------------------------------------------------------------------- /i18n-url-query-param/views/pages/app/index.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | {{ i18n . "page.app.index.title" }} 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 |
7 |
8 |
9 | 12 | Please note: Language listed here randomly to demostartion aah framework Internationalization (i18n) using URL Query String, no specific order.
13 | Credit: Text translated using translate.google.com 14 |
15 |


16 | aah framework logo 17 |

{{ i18n . "page.app.index.welcome_text" }}

18 |

19 |
20 | {{ i18n . "page.app.index.notes" }} 21 |
22 |
23 |
24 | {{- end }} 25 | -------------------------------------------------------------------------------- /oauth2-social-login/.gitignore: -------------------------------------------------------------------------------- 1 | # .gitignore config 2 | 3 | # aah application 4 | aah.go 5 | aah_*_vfs.go 6 | *.pid 7 | build/ 8 | app/generated 9 | # aah application - end 10 | vendor/*/ 11 | 12 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 13 | *.o 14 | *.a 15 | *.so 16 | 17 | # Folders 18 | _obj 19 | _test 20 | 21 | # Architecture specific extensions/prefixes 22 | *.[568vq] 23 | [568vq].out 24 | 25 | *.cgo1.go 26 | *.cgo2.c 27 | _cgo_defun.c 28 | _cgo_gotypes.go 29 | _cgo_export.* 30 | 31 | _testmain.go 32 | 33 | *.exe 34 | *.test 35 | *.prof 36 | -------------------------------------------------------------------------------- /oauth2-social-login/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

Example - OAuth2 Social Login

4 |

5 | 6 | This example demonstrates OAuth2 3-legged Flow implementation with aah framework. It does social login with Facebook, Google and Github. 7 | 8 | Learn more about [OAuth2 Auth scheme](https://docs.aahframework.org/auth-schemes/oauth2.html) 9 | 10 | ### Get aah examples 11 | 12 | ```bash 13 | git clone https://github.com/go-aah/examples.git aah-examples 14 | ``` 15 | 16 | ### Run this example 17 | 18 | **Step 1:** 19 | 20 | First, configure the OAuth2 provider(s) Client ID and Secret in the `security.conf`. Initially, to try with one provider, simply configure that one alone. 21 | 22 | **Step 2:** 23 | 24 | ```bash 25 | cd aah-examples/oauth2-social-login 26 | aah run 27 | ``` 28 | 29 | ### Visit this URL 30 | 31 | * http://localhost:8080 32 | 33 | In application home page, click on the provider icon :smile:. 34 | -------------------------------------------------------------------------------- /oauth2-social-login/app/controllers/app.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "aahframe.work" 5 | 6 | "aahframework.org/examples/oauth2-social-login/app/models" 7 | ) 8 | 9 | // AppController struct application controller 10 | type AppController struct { 11 | *aah.Context 12 | } 13 | 14 | // Index method is application home page. 15 | func (c *AppController) Index() { 16 | data := aah.Data{ 17 | "Greet": models.Greet{ 18 | Message: "aah framework - OAuth2 Social Login", 19 | }, 20 | } 21 | 22 | c.Reply().Ok().HTML(data) 23 | } 24 | 25 | // Success method is to display successful sign-in. 26 | func (c *AppController) Success() { 27 | } 28 | 29 | // Logout method does logout subject. 30 | func (c *AppController) Logout() { 31 | c.Subject().Logout() 32 | c.Reply().Redirect(c.RouteURL("index")) 33 | } 34 | -------------------------------------------------------------------------------- /oauth2-social-login/app/models/greet.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // Greet holds the greeting message. 4 | type Greet struct { 5 | Message string `json:"message"` 6 | } 7 | -------------------------------------------------------------------------------- /oauth2-social-login/app/security/authorization_provider.go: -------------------------------------------------------------------------------- 1 | package security 2 | 3 | import ( 4 | "aahframe.work/config" 5 | "aahframe.work/security/authc" 6 | "aahframe.work/security/authz" 7 | ) 8 | 9 | var _ authz.Authorizer = (*AuthorizationProvider)(nil) 10 | 11 | // AuthorizationProvider struct implements `authz.Authorizer` interface. 12 | type AuthorizationProvider struct { 13 | } 14 | 15 | // Init method initializes the AuthorizationProvider, this method gets called 16 | // during server start up. 17 | func (a *AuthorizationProvider) Init(cfg *config.Config) error { 18 | 19 | // NOTE: Init is called on application startup 20 | 21 | return nil 22 | } 23 | 24 | // GetAuthorizationInfo method is `authz.Authorizer` interface. 25 | // 26 | // GetAuthorizationInfo method gets called after authentication is successful 27 | // to get Subject's (aka User) access control information such as roles and permissions. 28 | func (a *AuthorizationProvider) GetAuthorizationInfo(authcInfo *authc.AuthenticationInfo) *authz.AuthorizationInfo { 29 | //‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ 30 | // This code snippet provided as a reference 31 | // 32 | // Call your appropriate datasource here (such as DB, API, etc) 33 | // to get the subject (aka user) authorization details (roles, permissions) 34 | //__________________________________________________________________________ 35 | 36 | // authorities := models.FindUserByEmail(authcInfo.PrimaryPrincipal().Value) 37 | 38 | authzInfo := authz.NewAuthorizationInfo() 39 | // authzInfo.AddRole(authorities.Roles...) 40 | // authzInfo.AddPermissionString(authorities.Permissions...) 41 | 42 | return authzInfo 43 | } 44 | -------------------------------------------------------------------------------- /oauth2-social-login/app/security/facebook/subject_principal_provider.go: -------------------------------------------------------------------------------- 1 | package facebook 2 | 3 | import ( 4 | aah "aahframe.work" 5 | "aahframe.work/ahttp" 6 | "aahframe.work/config" 7 | ess "aahframe.work/essentials" 8 | "aahframe.work/security/authc" 9 | "aahframe.work/security/scheme" 10 | "golang.org/x/oauth2" 11 | "gopkg.in/resty.v1" 12 | ) 13 | 14 | var _ authc.PrincipalProvider = (*SubjectPrincipalProvider)(nil) 15 | 16 | type FacebookUserInfo struct { 17 | ID string `json:"id"` 18 | Name string `json:"name"` 19 | Email string `json:"email"` 20 | } 21 | 22 | // SubjectPrincipalProvider struct implements interface authc.PrincipalProvider. 23 | type SubjectPrincipalProvider struct{} 24 | 25 | // Init method initializes the SubjectPrincipalProvider, Init method gets called 26 | // during aah server start up. 27 | func (a *SubjectPrincipalProvider) Init(appCfg *config.Config) error { 28 | // NOTE: Init is called on application startup 29 | return nil 30 | } 31 | 32 | // Principals method is called to get Subject's Principals information. 33 | func (a *SubjectPrincipalProvider) Principal(keyName string, v ess.Valuer) ([]*authc.Principal, error) { 34 | token := v.Get(aah.KeyOAuth2Token).(*oauth2.Token) 35 | fbAuth := aah.App().SecurityManager().AuthScheme(keyName).(*scheme.OAuth2) 36 | fbClient := resty.NewWithClient(fbAuth.Client(token)) 37 | 38 | resp, err := fbClient.R(). 39 | SetHeader(ahttp.HeaderAccept, ahttp.ContentTypeJSON.Mime). 40 | SetResult(FacebookUserInfo{}). 41 | Get("https://graph.facebook.com/v3.0/me?fields=name,email") 42 | if err != nil { 43 | return nil, err 44 | } 45 | userInfo := resp.Result().(*FacebookUserInfo) 46 | 47 | principals := make([]*authc.Principal, 0) 48 | principals = append(principals, &authc.Principal{Realm: "Facebook", IsPrimary: true, Claim: "Email", Value: userInfo.Email}) 49 | principals = append(principals, &authc.Principal{Realm: "Facebook", Claim: "ID", Value: userInfo.ID}) 50 | principals = append(principals, &authc.Principal{Realm: "Facebook", Claim: "Name", Value: userInfo.Name}) 51 | 52 | return principals, nil 53 | } 54 | -------------------------------------------------------------------------------- /oauth2-social-login/app/security/github/subject_principal_provider.go: -------------------------------------------------------------------------------- 1 | package facebook 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "net/http" 7 | 8 | "aahframe.work" 9 | "aahframe.work/config" 10 | "aahframe.work/essentials" 11 | "aahframe.work/security/authc" 12 | "aahframe.work/security/scheme" 13 | "github.com/google/go-github/github" 14 | "golang.org/x/oauth2" 15 | ) 16 | 17 | var _ authc.PrincipalProvider = (*SubjectPrincipalProvider)(nil) 18 | 19 | // SubjectPrincipalProvider struct implements interface authc.PrincipalProvider. 20 | type SubjectPrincipalProvider struct{} 21 | 22 | // Init method initializes the SubjectPrincipalProvider, Init method gets called 23 | // during aah server start up. 24 | func (a *SubjectPrincipalProvider) Init(appCfg *config.Config) error { 25 | // NOTE: Init is called on application startup 26 | return nil 27 | } 28 | 29 | // Principals method is called to get Subject's Principals information. 30 | func (a *SubjectPrincipalProvider) Principal(keyName string, v ess.Valuer) ([]*authc.Principal, error) { 31 | token := v.Get(aah.KeyOAuth2Token).(*oauth2.Token) 32 | githubAuth := aah.App().SecurityManager().AuthScheme(keyName).(*scheme.OAuth2) 33 | githubClient := github.NewClient(githubAuth.Client(token)) 34 | 35 | userInfo, resp, err := githubClient.Users.Get(context.Background(), "") 36 | if err != nil || resp.StatusCode != http.StatusOK || userInfo == nil || userInfo.ID == nil { 37 | return nil, fmt.Errorf("unable to get user info from google") 38 | } 39 | 40 | principals := make([]*authc.Principal, 0) 41 | principals = append(principals, &authc.Principal{Realm: "GitHub", IsPrimary: true, Claim: "Email", Value: userInfo.GetEmail()}) 42 | principals = append(principals, &authc.Principal{Realm: "GitHub", Claim: "ID", Value: fmt.Sprintf("%v", userInfo.GetID())}) 43 | principals = append(principals, &authc.Principal{Realm: "GitHub", Claim: "Name", Value: userInfo.GetName()}) 44 | 45 | return principals, nil 46 | } 47 | -------------------------------------------------------------------------------- /oauth2-social-login/app/security/google/subject_principal_provider.go: -------------------------------------------------------------------------------- 1 | package facebook 2 | 3 | import ( 4 | "fmt" 5 | 6 | "aahframe.work" 7 | "aahframe.work/config" 8 | "aahframe.work/essentials" 9 | "aahframe.work/security/authc" 10 | "aahframe.work/security/scheme" 11 | "golang.org/x/oauth2" 12 | google "google.golang.org/api/oauth2/v2" 13 | ) 14 | 15 | var _ authc.PrincipalProvider = (*SubjectPrincipalProvider)(nil) 16 | 17 | // SubjectPrincipalProvider struct implements interface authc.PrincipalProvider. 18 | type SubjectPrincipalProvider struct{} 19 | 20 | // Init method initializes the SubjectPrincipalProvider, Init method gets called 21 | // during aah server start up. 22 | func (a *SubjectPrincipalProvider) Init(appCfg *config.Config) error { 23 | // NOTE: Init is called on application startup 24 | return nil 25 | } 26 | 27 | // Principals method is called to get Subject's Principals information. 28 | func (a *SubjectPrincipalProvider) Principal(keyName string, v ess.Valuer) ([]*authc.Principal, error) { 29 | token := v.Get(aah.KeyOAuth2Token).(*oauth2.Token) 30 | googleAuth := aah.App().SecurityManager().AuthScheme(keyName).(*scheme.OAuth2) 31 | googleService, err := google.New(googleAuth.Client(token)) 32 | if err != nil { 33 | return nil, fmt.Errorf("unable to create google service") 34 | } 35 | 36 | userInfo, err := googleService.Userinfo.Get().Do() 37 | if err != nil || userInfo == nil || userInfo.Id == "" { 38 | return nil, fmt.Errorf("unable to get user info from google") 39 | } 40 | 41 | principals := make([]*authc.Principal, 0) 42 | principals = append(principals, &authc.Principal{Realm: "Google", IsPrimary: true, Claim: "Email", Value: userInfo.Email}) 43 | principals = append(principals, &authc.Principal{Realm: "Google", Claim: "ID", Value: userInfo.Id}) 44 | principals = append(principals, &authc.Principal{Realm: "Google", Claim: "Name", Value: userInfo.Name}) 45 | 46 | return principals, nil 47 | } 48 | -------------------------------------------------------------------------------- /oauth2-social-login/app/security/post_auth_event.go: -------------------------------------------------------------------------------- 1 | package security 2 | 3 | import "aahframe.work" 4 | 5 | // PostAuthEvent method called after successful authentication and authorization. 6 | func PostAuthEvent(e *aah.Event) { 7 | ctx := e.Data.(*aah.Context) 8 | ctx.Log().Info("Method security.PostAuthEvent called") 9 | 10 | sub := ctx.Subject() 11 | ctx.Session().Set("Realm", sub.PrimaryPrincipal().Realm) 12 | ctx.Session().Set("Username", sub.PrimaryPrincipal().Value) 13 | ctx.Session().Set("ID", sub.Principal("ID").Value) 14 | ctx.Session().Set("Name", sub.Principal("Name").Value) 15 | } 16 | -------------------------------------------------------------------------------- /oauth2-social-login/config/env/dev.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Development Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | dev { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Log Configuration 9 | # 10 | # Doc: https://docs.aahframework.org/logging.html 11 | # Doc: https://docs.aahframework.org/log-config.html 12 | # ----------------------------------------------------------------------------- 13 | log { 14 | receiver = "console" 15 | level = "debug" 16 | format = "text" 17 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 18 | color = true 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /oauth2-social-login/config/env/prod.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Production Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | prod { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Runtime configuration 9 | # Doc: https://docs.aahframework.org/app-config.html#section-runtime 10 | # ----------------------------------------------------------------------------- 11 | runtime { 12 | debug { 13 | strip_src_base = true 14 | } 15 | } 16 | 17 | # ----------------------------------------------------------------------------- 18 | # Log Configuration 19 | # 20 | # Doc: https://docs.aahframework.org/logging.html 21 | # Doc: https://docs.aahframework.org/log-config.html 22 | # ----------------------------------------------------------------------------- 23 | log { 24 | receiver = "file" 25 | file = "oauth2-social-login.log" 26 | level = "warn" 27 | format = "text" 28 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 29 | color = false 30 | rotate { 31 | policy = "daily" 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /oauth2-social-login/go.mod: -------------------------------------------------------------------------------- 1 | module aahframework.org/examples/oauth2-social-login 2 | 3 | require ( 4 | aahframe.work v0.12.2 5 | aahframe.work/minify/html v0.2.0 6 | github.com/google/go-github v17.0.0+incompatible 7 | github.com/google/go-querystring v1.0.0 // indirect 8 | golang.org/x/oauth2 v0.0.0-20181003184128-c57b0facaced 9 | google.golang.org/api v0.0.0-20181129220737-af4fc4062c26 10 | gopkg.in/resty.v1 v1.10.2 11 | ) 12 | -------------------------------------------------------------------------------- /oauth2-social-login/i18n/messages.en: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # i18n messages for oauth2-social-login application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # ----------------------------------------------------------------------------- 6 | 7 | # This structure is example purpose 8 | # So choose your suitable structure for your application 9 | label { 10 | pages { 11 | app { 12 | index { 13 | title = "aah framework - OAuth2 Social Login - Home" 14 | } 15 | success { 16 | title = "You have successfully Logged in with" 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /oauth2-social-login/static/css/aah.css: -------------------------------------------------------------------------------- 1 | /* 2 | Minimal aah framework application template CSS. 3 | Based on your need choose your CSS framework. 4 | */ 5 | 6 | html { 7 | font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; 8 | -webkit-text-size-adjust: 100%; 9 | -ms-text-size-adjust: 100%; 10 | } 11 | 12 | body { 13 | margin: 0; 14 | } 15 | 16 | .container { 17 | padding-right: 15px; 18 | padding-left: 15px; 19 | margin-right: auto; 20 | margin-left: auto; 21 | } 22 | @media (min-width: 992px) { 23 | .container { 24 | width: 970px; 25 | } 26 | } 27 | @media (min-width: 1200px) { 28 | .container { 29 | width: 1170px; 30 | } 31 | } 32 | 33 | .row { 34 | margin-right: -15px; 35 | margin-left: -15px; 36 | } 37 | 38 | .text-center { 39 | text-align: center; 40 | } 41 | 42 | .welcome-msg { 43 | padding-top: 30px; 44 | padding-bottom: 30px; 45 | margin-bottom: 30px; 46 | color: inherit; 47 | } 48 | 49 | .fa { 50 | padding: 20px; 51 | font-size: 30px; 52 | width: 30px; 53 | text-align: center; 54 | text-decoration: none; 55 | margin: 5px 2px; 56 | border-radius: 50%; 57 | } 58 | 59 | .fa:hover { 60 | opacity: 0.7; 61 | } 62 | 63 | .fa-facebook { 64 | background: #3B5998; 65 | color: white; 66 | } 67 | 68 | .fa-google { 69 | background: #dd4b39; 70 | color: white; 71 | } 72 | 73 | .fa-github { 74 | background: #444444; 75 | color: white; 76 | } 77 | -------------------------------------------------------------------------------- /oauth2-social-login/static/img/aah-framework-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/oauth2-social-login/static/img/aah-framework-logo.png -------------------------------------------------------------------------------- /oauth2-social-login/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/oauth2-social-login/static/img/favicon.ico -------------------------------------------------------------------------------- /oauth2-social-login/static/js/aah.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/oauth2-social-login/static/js/aah.js -------------------------------------------------------------------------------- /oauth2-social-login/static/robots.txt: -------------------------------------------------------------------------------- 1 | # Prevents all robots visiting your site. 2 | User-agent: * 3 | Disallow: / 4 | -------------------------------------------------------------------------------- /oauth2-social-login/views/common/error_footer.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /oauth2-social-login/views/common/error_header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ .Error.Code }} {{ .Error.Message }} 6 | 7 | 8 | 34 | 35 | -------------------------------------------------------------------------------- /oauth2-social-login/views/common/footer_scripts.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /oauth2-social-login/views/common/head_tags.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /oauth2-social-login/views/errors/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ include "/common/error_header.html" . -}} 4 | 5 |
{{ with .Error }} 6 |
7 |
8 | {{ .Code }} {{ .Message }} 9 |
10 |
{{ end }} 11 |
12 | {{ include "/common/error_footer.html" . -}} 13 | 14 | 15 | -------------------------------------------------------------------------------- /oauth2-social-login/views/errors/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ include "/common/error_header.html" . -}} 4 | 5 |
{{ with .Error }} 6 |
7 |
8 | {{ .Code }} {{ .Message }} 9 |
10 |
{{ end }} 11 |
12 | {{ include "/common/error_footer.html" . -}} 13 | 14 | 15 | -------------------------------------------------------------------------------- /oauth2-social-login/views/layouts/master.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ template "title" . }} 8 | {{ include "/common/head_tags.html" . }} 9 | 10 | 11 | {{ template "body" . -}} 12 | {{ include "/common/footer_scripts.html" . }} 13 | 14 | 15 | -------------------------------------------------------------------------------- /oauth2-social-login/views/pages/app/index.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | {{ i18n . "label.pages.app.index.title" }} 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 |
7 |
8 | aah framework logo 9 |

{{ .Greet.Message }}

10 | 11 |

12 |

Login with

13 |
14 |
15 |    16 |    17 | 18 |
19 |
20 |
21 | {{- end }} 22 | -------------------------------------------------------------------------------- /oauth2-social-login/views/pages/app/success.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | {{ i18n . "label.pages.app.success.title" }} {{ session . "Realm" }} - OAuth2 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 |
7 | 12 |
13 |
14 |

You have successfully Logged in with {{ session . "Realm" }}


15 | ID: {{ session . "ID" }}
16 | Username : {{ session . "Username" }}
17 | Name : {{ session . "Name" }}
18 |

19 | Logout 20 |
21 |
22 | {{- end }} 23 | -------------------------------------------------------------------------------- /rest-api-basic-auth/.gitignore: -------------------------------------------------------------------------------- 1 | # aah framework application - .gitignore 2 | 3 | aah.go 4 | *.pid 5 | build/ 6 | aah_*_vfs.go 7 | app/generated 8 | vendor/*/ 9 | # aah application - end 10 | 11 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 12 | *.o 13 | *.a 14 | *.so 15 | 16 | # Folders 17 | _obj 18 | _test 19 | 20 | # Architecture specific extensions/prefixes 21 | *.[568vq] 22 | [568vq].out 23 | 24 | *.cgo1.go 25 | *.cgo2.c 26 | _cgo_defun.c 27 | _cgo_gotypes.go 28 | _cgo_export.* 29 | 30 | _testmain.go 31 | 32 | *.exe 33 | *.test 34 | *.prof 35 | -------------------------------------------------------------------------------- /rest-api-basic-auth/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

Example - REST API Basic Auth

4 |

5 | 6 | This example demonstrates REST API Basic Auth with aah framework. aah REST API Basic Auth includes authentication and route authorization via routes config. 7 | 8 | aah supports basic auth mechanism in two ways, choose per use case - 9 | 10 | Realm | Description 11 | ----- | ----------- 12 | File | When you know a set of pre-defiend subjects (aka users), roles and permissions (roles and permissions values are optional though) 13 | Dynamic | Subject information lies in Data Source (DB, API provider, etc). Implementing interfaces `authc.Authenticator` and `authz.Authorizer` 14 | 15 | Learn more about [Security design](https://docs.aahframework.org/security-design.html), [Authentication](https://docs.aahframework.org/authentication.html) and [Authorization](https://docs.aahframework.org/authorization.html). 16 | 17 | ### Get aah exaamples 18 | 19 | ```bash 20 | git clone https://github.com/go-aah/examples.git aah-examples 21 | ``` 22 | 23 | ### Run this example 24 | 25 | ```bash 26 | cd aah-examples/rest-api-basic-auth 27 | aah run 28 | ``` 29 | 30 | ### Use a preferred REST client to make a request 31 | 32 | **Demo User Credentials** 33 | 34 | Username/Password | Roles & Permissions | IsLocked 35 | ----------------- | ------------------- | -------- 36 | user1@aahframework.org/welcome123 | Roles: "employee", "manager"
Permissions: "user:read,edit:reportee" | No 37 | user2@aahframework.org/welcome123 | Roles: "employee"
Permissions: N/A | No 38 | user3@aahframework.org/welcome123 | Roles: "employee"
Permissions: N/A | Yes 39 | admin@aahframework.org/welcome123 | Roles: "employee", "manager", "admin"
Permissions: "user:read,edit,delete:reportee" | No 40 | 41 |
42 | 43 | **API Endpoints** 44 | 45 | ``` 46 | GET / - Shows welcome message (Anonymous access) 47 | GET /v1/reportee/:email - Returns user data for given email address based on authorization (Secured) 48 | ``` 49 | 50 | ### Welcome Message 51 | 52 | Send GET request to http://localhost:8080/ 53 | 54 | Response: 55 | 56 | ```json 57 | {"message":"Welcome to aah framework - REST API Basic Auth Example"} 58 | ``` 59 | 60 | ### Get reportee data 61 | 62 | Send GET request to http://localhost:8080/v1/reportee/user1@aahframework.org with Basic Auth `user1@aahframework.org/welcome123` 63 | 64 | Resposne: 65 | 66 | ```json 67 | { 68 | "first_name": "East", 69 | "last_name": "Corner", 70 | "email": "user1@aahframework.org", 71 | "is_locked": false, 72 | "is_expried": false, 73 | "roles": [ 74 | "employee", 75 | "manager" 76 | ], 77 | "permission": [ 78 | "user:read,edit:reportee" 79 | ] 80 | } 81 | ``` 82 | 83 | Now, try various combinations with the above demo credentials. 84 | -------------------------------------------------------------------------------- /rest-api-basic-auth/app/controllers/app.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package controllers 6 | 7 | import ( 8 | "aahframe.work" 9 | "aahframework.org/examples/rest-api-basic-auth/app/models" 10 | ) 11 | 12 | // AppController struct application controller 13 | type AppController struct { 14 | *aah.Context 15 | } 16 | 17 | // Index method is application root API endpoint. 18 | func (c *AppController) Index() { 19 | c.Reply().Ok().JSON(models.Greet{ 20 | Message: "Welcome to aah framework - REST API Basic Auth Example", 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /rest-api-basic-auth/app/controllers/info.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package controllers 6 | 7 | import ( 8 | "net/http" 9 | 10 | "aahframe.work/essentials" 11 | 12 | "aahframe.work" 13 | 14 | "aahframework.org/examples/rest-api-basic-auth/app/models" 15 | ) 16 | 17 | // InfoController is demo purpose to send data for Authentication & Authoriization. 18 | type InfoController struct { 19 | AppController 20 | } 21 | 22 | // ReporteeInfo returns the reportee info for who access of, 23 | // role as `manager` and permission as `user:read:reportee`. 24 | // Look at above Interceptor for authorization check. 25 | func (c *InfoController) ReporteeInfo(email string) { 26 | userInfo := models.FindUserByEmail(email) 27 | if userInfo == nil { 28 | c.Reply().NotFound().JSON(aah.Data{ 29 | "message": "repotee not found", 30 | }) 31 | return 32 | } 33 | 34 | // Specfic case: admin user check 35 | if ess.IsSliceContainsString(userInfo.Roles, "admin") && !c.Subject().HasRole("admin") { 36 | c.Reply().Forbidden().JSON(aah.Data{"message": "access denied"}) 37 | return 38 | } 39 | 40 | c.Reply().Ok().JSON(userInfo) 41 | } 42 | 43 | // HandleError method invoked by aah error handling flow 44 | // Doc: https://aahframework.org/error-handling.html 45 | func (c *InfoController) HandleError(err *aah.Error) bool { 46 | switch err.Code { 47 | case http.StatusForbidden: 48 | c.Reply().Forbidden().JSON(aah.Data{ 49 | "message": "access denied", 50 | }) 51 | } 52 | return true 53 | } 54 | -------------------------------------------------------------------------------- /rest-api-basic-auth/app/models/greet.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package models 6 | 7 | // Greet holds the greeting message. 8 | type Greet struct { 9 | Message string `json:"message"` 10 | } 11 | -------------------------------------------------------------------------------- /rest-api-basic-auth/app/models/user.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package models 6 | 7 | // This is for demo purpose, set of users 8 | // Typically you will be using Database, API calls, LDAP, etc to get the Authentication 9 | // Information. 10 | 11 | // Key is email and value is User 12 | var users map[string]*User 13 | 14 | type ( 15 | // User struct hold the user details 16 | User struct { 17 | FirstName string `json:"first_name"` 18 | LastName string `json:"last_name"` 19 | Email string `json:"email"` 20 | Password string `json:"-"` 21 | IsLocked bool `json:"is_locked"` 22 | IsExpried bool `json:"is_expried"` 23 | Roles []string `json:"roles,omitempty"` 24 | Permissions []string `json:"permission,omitempty"` 25 | } 26 | ) 27 | 28 | // FindUserByEmail returns the user information for given email address. 29 | func FindUserByEmail(email string) *User { 30 | if u, found := users[email]; found { 31 | uf := *u 32 | return &uf 33 | } 34 | return nil 35 | } 36 | 37 | func init() { 38 | /* 39 | Creating User Information 40 | Learn about permission: http://docs.aahframework.org/security-permissions.html 41 | */ 42 | users = make(map[string]*User) 43 | 44 | users["user1@aahframework.org"] = &User{ 45 | FirstName: "East", 46 | LastName: "Corner", 47 | Password: "$2y$10$2A4GsJ6SmLAMvDe8XmTam.MSkKojdobBVJfIU7GiyoM.lWt.XV3H6", // welcome123 48 | Email: "user1@aahframework.org", 49 | Roles: []string{"employee", "manager"}, 50 | Permissions: []string{"user:read,edit:reportee"}, 51 | } 52 | 53 | users["user2@aahframework.org"] = &User{ 54 | FirstName: "West", 55 | LastName: "Corner", 56 | Password: "$2y$10$2A4GsJ6SmLAMvDe8XmTam.MSkKojdobBVJfIU7GiyoM.lWt.XV3H6", // welcome123 57 | Email: "user2@aahframework.org", 58 | Roles: []string{"employee"}, 59 | } 60 | 61 | users["user3@aahframework.org"] = &User{ 62 | FirstName: "South", 63 | LastName: "Corner", 64 | Password: "$2y$10$2A4GsJ6SmLAMvDe8XmTam.MSkKojdobBVJfIU7GiyoM.lWt.XV3H6", // welcome123 65 | Email: "user3@aahframework.org", 66 | Roles: []string{"employee"}, 67 | IsLocked: true, 68 | } 69 | 70 | users["admin@aahframework.org"] = &User{ 71 | FirstName: "Admin", 72 | LastName: "Corner", 73 | Password: "$2y$10$2A4GsJ6SmLAMvDe8XmTam.MSkKojdobBVJfIU7GiyoM.lWt.XV3H6", // welcome123 74 | Email: "admin@aahframework.org", 75 | Roles: []string{"employee", "manager", "admin"}, 76 | Permissions: []string{"user:read,edit,delete:reportee"}, 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /rest-api-basic-auth/app/security/basic_authentication_provider.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package security 6 | 7 | import ( 8 | "aahframe.work/config" 9 | "aahframe.work/security/authc" 10 | "aahframework.org/examples/rest-api-basic-auth/app/models" 11 | ) 12 | 13 | var _ authc.Authenticator = (*BasicAuthenticationProvider)(nil) 14 | 15 | // BasicAuthenticationProvider struct implements `authc.Authenticator` interface. 16 | type BasicAuthenticationProvider struct{} 17 | 18 | // Init method initializes the BasicAuthenticationProvider, this method gets called 19 | // during server start up. 20 | func (fa *BasicAuthenticationProvider) Init(cfg *config.Config) error { 21 | 22 | // NOTE: Init is called on application startup 23 | 24 | return nil 25 | } 26 | 27 | // GetAuthenticationInfo method is `authc.Authenticator` interface. It is called by Security Manager 28 | func (fa *BasicAuthenticationProvider) GetAuthenticationInfo(authcToken *authc.AuthenticationToken) (*authc.AuthenticationInfo, error) { 29 | 30 | // Basic Auth Values from authcToken 31 | // authcToken.Identity => username 32 | // authcToken.Credential => passowrd 33 | 34 | user := models.FindUserByEmail(authcToken.Identity) 35 | if user == nil { 36 | // No subject exists, return nil and error 37 | return nil, authc.ErrSubjectNotExists 38 | } 39 | 40 | // User found, now create authentication info and return to the framework 41 | authcInfo := authc.NewAuthenticationInfo() 42 | authcInfo.Principals = append(authcInfo.Principals, 43 | &authc.Principal{ 44 | Value: user.Email, 45 | IsPrimary: true, 46 | Realm: "inmemory", 47 | }) 48 | authcInfo.Credential = []byte(user.Password) 49 | authcInfo.IsLocked = user.IsLocked 50 | authcInfo.IsExpired = user.IsExpried 51 | 52 | return authcInfo, nil 53 | } 54 | -------------------------------------------------------------------------------- /rest-api-basic-auth/app/security/basic_authorization_provider.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package security 6 | 7 | import ( 8 | "aahframe.work/config" 9 | "aahframe.work/security/authc" 10 | "aahframe.work/security/authz" 11 | "aahframework.org/examples/rest-api-basic-auth/app/models" 12 | ) 13 | 14 | var _ authz.Authorizer = (*BasicAuthorizationProvider)(nil) 15 | 16 | // BasicAuthorizationProvider struct implements `authz.Authorizer` interface. 17 | type BasicAuthorizationProvider struct{} 18 | 19 | // Init method initializes the BasicAuthorizationProvider, this method gets called 20 | // during server start up. 21 | func (fa *BasicAuthorizationProvider) Init(cfg *config.Config) error { 22 | 23 | // NOTE: Init is called on application startup 24 | 25 | return nil 26 | } 27 | 28 | // GetAuthorizationInfo method is `authz.Authorizer` interface. 29 | // 30 | // GetAuthorizationInfo method gets called after authentication is successful 31 | // to get Subject's (aka User) access control information such as roles and permissions. 32 | func (fa *BasicAuthorizationProvider) GetAuthorizationInfo(authcInfo *authc.AuthenticationInfo) *authz.AuthorizationInfo { 33 | authorities := models.FindUserByEmail(authcInfo.PrimaryPrincipal().Value) 34 | 35 | authzInfo := authz.NewAuthorizationInfo() 36 | authzInfo.AddRole(authorities.Roles...) 37 | authzInfo.AddPermissionString(authorities.Permissions...) 38 | 39 | return authzInfo 40 | } 41 | -------------------------------------------------------------------------------- /rest-api-basic-auth/config/env/dev.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Development Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | dev { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Log Configuration 9 | # 10 | # Doc: https://docs.aahframework.org/logging.html 11 | # Doc: https://docs.aahframework.org/log-config.html 12 | # ----------------------------------------------------------------------------- 13 | log { 14 | receiver = "console" 15 | level = "debug" 16 | format = "text" 17 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 18 | color = true 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /rest-api-basic-auth/config/env/prod.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Production Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | prod { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Runtime configuration 9 | # Doc: https://docs.aahframework.org/app-config.html#section-runtime 10 | # ----------------------------------------------------------------------------- 11 | runtime { 12 | debug { 13 | strip_src_base = true 14 | } 15 | } 16 | 17 | # ----------------------------------------------------------------------------- 18 | # Log Configuration 19 | # 20 | # Doc: https://docs.aahframework.org/logging.html 21 | # Doc: https://docs.aahframework.org/log-config.html 22 | # ----------------------------------------------------------------------------- 23 | log { 24 | receiver = "file" 25 | file = "rest-api-basic-auth.log" 26 | level = "warn" 27 | format = "text" 28 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 29 | color = false 30 | rotate { 31 | policy = "daily" 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /rest-api-basic-auth/config/routes.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # rest-api-basic-auth - Application Routes Configuration 3 | # 4 | # Refer documentation to explore and configure routes. 5 | # Doc: https://docs.aahframework.org/routing.html 6 | # ----------------------------------------------------------------------------- 7 | 8 | domains { 9 | #------------------------------------------------------------------------------ 10 | # Domain/subdomain Key Name 11 | # Choose an `unique keyname` to define domain section and its configuration. 12 | # Tip: domain name address, port no values to create a domain key, etc. 13 | # 14 | # Doc: https://docs.aahframework.org/routes-config.html#domain-configuration 15 | #------------------------------------------------------------------------------ 16 | localhost { 17 | name = "rest-api-basic-auth routes" 18 | host = "localhost" 19 | 20 | # ----------------------------------------------------------------------------- 21 | # Routes Configuration 22 | # 23 | # Doc: https://docs.aahframework.org/routes-config.html#routes-configuration 24 | # ----------------------------------------------------------------------------- 25 | routes { 26 | index { 27 | path = "/" 28 | controller = "AppController" 29 | auth = "anonymous" 30 | } 31 | 32 | v1_group { 33 | path = "/v1" 34 | 35 | routes { 36 | reportee_info { 37 | path = "/reportee/:email" 38 | controller = "InfoController" 39 | action = "ReporteeInfo" 40 | auth = "basic_auth" 41 | authorization { 42 | satisfy = "both" 43 | roles = [ 44 | "hasrole(manager)" 45 | ] 46 | permissions = [ 47 | "ispermitted(user:read:reportee)" 48 | ] 49 | } 50 | } 51 | } 52 | } 53 | 54 | } # end - routes 55 | 56 | } # end - localhost 57 | 58 | } # end - domains 59 | -------------------------------------------------------------------------------- /rest-api-basic-auth/config/security.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # rest-api-basic-auth - Application Security Configuration 3 | # 4 | # Refer documentation to explore and customize the configurations. 5 | # Doc: https://docs.aahframework.org/security-config.html 6 | # ----------------------------------------------------------------------------- 7 | 8 | security { 9 | auth_schemes { 10 | # ----------------------------------------------------------------------------- 11 | # Basic auth scheme 12 | # Choose a unique key name. It gets used as route auth. 13 | # 14 | # Doc: https://docs.aahframework.org/auth-schemes/basic.html 15 | # ----------------------------------------------------------------------------- 16 | basic_auth { 17 | scheme = "basic" 18 | realm_name = "Protected APIs" 19 | authenticator = "security/BasicAuthenticationProvider" 20 | authorizer = "security/BasicAuthorizationProvider" 21 | password_encoder = "bcrypt" 22 | } 23 | } 24 | 25 | # --------------------------------------------------------------------------- 26 | # HTTP Secure Header(s) 27 | # Application security headers with many safe defaults. 28 | # Doc: https://docs.aahframework.org/security-config.html#section-http-header 29 | # 30 | # Tip: Quick way to verify secure headers - https://securityheaders.io 31 | # --------------------------------------------------------------------------- 32 | http_header { 33 | enable = true 34 | xxssp = "" 35 | xfo = "DENY" 36 | rp = "" 37 | xpcdp = "" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /rest-api-basic-auth/go.mod: -------------------------------------------------------------------------------- 1 | module aahframework.org/examples/rest-api-basic-auth 2 | 3 | require aahframe.work v0.12.2 4 | -------------------------------------------------------------------------------- /rest-api-jwt-auth/.gitignore: -------------------------------------------------------------------------------- 1 | # aah framework application - .gitignore 2 | 3 | aah.go 4 | *.pid 5 | build/ 6 | aah_*_vfs.go 7 | app/generated 8 | # aah application - end 9 | vendor/*/ 10 | 11 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 12 | *.o 13 | *.a 14 | *.so 15 | 16 | # Folders 17 | _obj 18 | _test 19 | 20 | # Architecture specific extensions/prefixes 21 | *.[568vq] 22 | [568vq].out 23 | 24 | *.cgo1.go 25 | *.cgo2.c 26 | _cgo_defun.c 27 | _cgo_gotypes.go 28 | _cgo_export.* 29 | 30 | _testmain.go 31 | 32 | *.exe 33 | *.test 34 | *.prof 35 | -------------------------------------------------------------------------------- /rest-api-jwt-auth/app/controllers/app.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package controllers 6 | 7 | import ( 8 | "time" 9 | 10 | "aahframe.work" 11 | "aahframe.work/essentials" 12 | "aahframework.org/examples/rest-api-jwt-auth/app/models" 13 | "aahframework.org/examples/rest-api-jwt-auth/app/security" 14 | "github.com/dgrijalva/jwt-go" 15 | "golang.org/x/crypto/bcrypt" 16 | ) 17 | 18 | // AppController struct application controller 19 | type AppController struct { 20 | *aah.Context 21 | } 22 | 23 | // Index method is application root API endpoint. 24 | func (c *AppController) Index() { 25 | c.Reply().Ok().JSON(models.Greet{ 26 | Message: "Welcome to aah framework - REST API JWT Auth using Generic Auth scheme", 27 | }) 28 | } 29 | 30 | // Token method validates the given username and password the 31 | // generates the JWT token. 32 | func (c *AppController) Token(userToken *models.UserToken) { 33 | if ess.IsStrEmpty(userToken.Username) || ess.IsStrEmpty(userToken.Password) { 34 | c.Reply().BadRequest().JSON(aah.Data{ 35 | "message": "bad request", 36 | }) 37 | return 38 | } 39 | 40 | // get the user details by username 41 | user := models.FindUserByEmail(userToken.Username) 42 | if user == nil || user.IsExpried || user.IsLocked { 43 | c.Reply().Unauthorized().JSON(aah.Data{ 44 | "message": "invalid credentials", 45 | }) 46 | return 47 | } 48 | 49 | // validate password 50 | if err := bcrypt.CompareHashAndPassword(user.Password, []byte(userToken.Password)); err != nil { 51 | c.Reply().Unauthorized().JSON(aah.Data{ 52 | "message": "invalid credentials", 53 | }) 54 | return 55 | } 56 | 57 | // create JWT claims 58 | claims := jwt.MapClaims{} 59 | claims["username"] = user.Email 60 | claims["exp"] = time.Now().Add(time.Hour * 72).Unix() 61 | 62 | // Generate JWT token string 63 | token, err := security.GenerateToken(claims) 64 | if err != nil { 65 | c.Log().Error(err) 66 | c.Reply().InternalServerError().JSON(aah.Data{ 67 | "message": "Whoops! something went wrong...", 68 | }) 69 | return 70 | } 71 | 72 | // everything went good, respond token 73 | c.Reply().Ok().JSON(aah.Data{ 74 | "token_type": "bearer", 75 | "token": token, 76 | }) 77 | } 78 | -------------------------------------------------------------------------------- /rest-api-jwt-auth/app/controllers/info.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package controllers 6 | 7 | import ( 8 | "net/http" 9 | 10 | "aahframe.work" 11 | "aahframework.org/examples/rest-api-jwt-auth/app/models" 12 | ) 13 | 14 | // InfoController is to demostrate the REST API endpoints for Authentication & Authorization. 15 | type InfoController struct { 16 | AppController 17 | } 18 | 19 | // ReporteeInfo returns the reportee info for who access of, 20 | // role as `manager` and permission as `user:read:reportee`. 21 | // Look at above Interceptor for authorization check. 22 | func (i *InfoController) ReporteeInfo(email string) { 23 | userInfo := models.FindUserByEmail(email) 24 | if userInfo == nil { 25 | i.Reply().NotFound().JSON(aah.Data{ 26 | "message": "repotee not found", 27 | }) 28 | return 29 | } 30 | 31 | i.Reply().Ok().JSON(userInfo) 32 | } 33 | 34 | // HandleError method invoked by aah error handling flow 35 | // Doc: https://aahframework.org/error-handling.html 36 | func (i *InfoController) HandleError(err *aah.Error) bool { 37 | switch err.Code { 38 | case http.StatusForbidden: 39 | i.Reply().Forbidden().JSON(aah.Data{ 40 | "message": "access denied", 41 | }) 42 | } 43 | return true 44 | } 45 | -------------------------------------------------------------------------------- /rest-api-jwt-auth/app/models/greet.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package models 6 | 7 | // Greet holds the greeting message. 8 | type Greet struct { 9 | Message string `json:"message"` 10 | } 11 | -------------------------------------------------------------------------------- /rest-api-jwt-auth/app/security/authentication_provider.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package security 6 | 7 | import ( 8 | "strings" 9 | 10 | "aahframe.work/config" 11 | "aahframe.work/essentials" 12 | "aahframe.work/log" 13 | "aahframe.work/security/authc" 14 | "github.com/dgrijalva/jwt-go" 15 | ) 16 | 17 | var _ authc.Authenticator = (*AuthenticationProvider)(nil) 18 | 19 | // AuthenticationProvider struct implements `authc.Authenticator` interface. 20 | type AuthenticationProvider struct{} 21 | 22 | //‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ 23 | // AuthenticationProvider methods 24 | //___________________________________ 25 | 26 | // Init method initializes the AuthenticationProvider, this method gets called 27 | // during server start up. 28 | func (a *AuthenticationProvider) Init(cfg *config.Config) error { 29 | // NOTE: Init is called on application startup 30 | return nil 31 | } 32 | 33 | // GetAuthenticationInfo method is `authc.Authenticator` interface. It is called by Security Manager. 34 | func (a *AuthenticationProvider) GetAuthenticationInfo(authcToken *authc.AuthenticationToken) (*authc.AuthenticationInfo, error) { 35 | // authcToken.Identity is complete value of "Authorization" HTTP header or 36 | // configured `security.auth_schemes.jwt_auth.header.identity` header value 37 | // 38 | // values[0] ==> Bearer 39 | // values[1] ==> JWT token 40 | values := strings.Fields(authcToken.Identity) 41 | if len(values) != 2 || ess.IsStrEmpty(values[1]) { 42 | log.Error("Token is not provided") 43 | return nil, authc.ErrAuthenticationFailed 44 | } 45 | 46 | // Validate the JWT token 47 | token, err := jwt.Parse(values[1], jwtKeyFunc) 48 | if err != nil || !token.Valid { 49 | log.Errorf("Error occurred '%v' or token is not valid", err) 50 | return nil, authc.ErrAuthenticationFailed 51 | } 52 | 53 | claims := token.Claims.(jwt.MapClaims) 54 | 55 | // User found and token validated. 56 | // Now create authentication info and return to the framework 57 | authcInfo := authc.NewAuthenticationInfo() 58 | authcInfo.Principals = append(authcInfo.Principals, 59 | &authc.Principal{ 60 | Realm: "inmemory", 61 | Claim: "Username", 62 | Value: claims["username"].(string), 63 | IsPrimary: true, 64 | }) 65 | 66 | return authcInfo, nil 67 | } 68 | -------------------------------------------------------------------------------- /rest-api-jwt-auth/app/security/authorization_provider.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package security 6 | 7 | import ( 8 | "aahframe.work/config" 9 | "aahframe.work/security/authc" 10 | "aahframe.work/security/authz" 11 | "aahframework.org/examples/rest-api-jwt-auth/app/models" 12 | ) 13 | 14 | var _ authz.Authorizer = (*AuthorizationProvider)(nil) 15 | 16 | // AuthorizationProvider struct implements `authz.Authorizer` interface. 17 | type AuthorizationProvider struct{} 18 | 19 | // Init method initializes the AuthorizationProvider, this method gets called 20 | // during server start up. 21 | func (a *AuthorizationProvider) Init(cfg *config.Config) error { 22 | // NOTE: Init is called on application startup 23 | return nil 24 | } 25 | 26 | // GetAuthorizationInfo method is `authz.Authorizer` interface. 27 | // 28 | // GetAuthorizationInfo method gets called after authentication is successful 29 | // to get Subject's (aka User) access control information such as roles and permissions. 30 | // It is called by Security Manager. 31 | func (a *AuthorizationProvider) GetAuthorizationInfo(authcInfo *authc.AuthenticationInfo) *authz.AuthorizationInfo { 32 | authorities := models.FindUserByEmail(authcInfo.PrimaryPrincipal().Value) 33 | 34 | authzInfo := authz.NewAuthorizationInfo() 35 | authzInfo.AddRole(authorities.Roles...) 36 | authzInfo.AddPermissionString(authorities.Permissions...) 37 | 38 | return authzInfo 39 | } 40 | -------------------------------------------------------------------------------- /rest-api-jwt-auth/app/security/jwt.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package security 6 | 7 | import ( 8 | "fmt" 9 | "log" 10 | 11 | "aahframe.work" 12 | 13 | "github.com/dgrijalva/jwt-go" 14 | ) 15 | 16 | // JWT config values 17 | var ( 18 | JWTSigningMethod string 19 | JWTSigningKey []byte 20 | ) 21 | 22 | //‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ 23 | // Package methods 24 | //___________________________________ 25 | 26 | // LoadJWTconfig JWT setting into variable on server startup. 27 | func LoadJWTconfig(_ *aah.Event) { 28 | JWTSigningMethod = aah.App().Config().StringDefault("security.auth_schemes.jwt_auth.sign.method", "HS256") 29 | 30 | if signingKey, found := aah.App().Config().String("security.auth_schemes.jwt_auth.sign.key"); found { 31 | JWTSigningKey = []byte(signingKey) 32 | } else { 33 | log.Fatal("security.auth_schemes.jwt_auth.sign.key is required") 34 | } 35 | } 36 | 37 | func GenerateToken(claims jwt.MapClaims) (string, error) { 38 | token := createToken() 39 | token.Claims = claims 40 | 41 | // Generate encoded token and send it as response. 42 | signedToken, err := token.SignedString(JWTSigningKey) 43 | if err != nil { 44 | return "", err 45 | } 46 | return signedToken, nil 47 | } 48 | 49 | //‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ 50 | // JWT Unexported methods 51 | //___________________________________ 52 | 53 | // createToken return token based on config value. 54 | // `security.auth_schemes.jwt_auth.sign.method` on security.conf 55 | func createToken() *jwt.Token { 56 | switch JWTSigningMethod { 57 | case "HS256": 58 | return jwt.New(jwt.SigningMethodHS256) 59 | case "HS384": 60 | return jwt.New(jwt.SigningMethodHS384) 61 | case "HS512": 62 | return jwt.New(jwt.SigningMethodHS512) 63 | } 64 | return nil 65 | } 66 | 67 | // jwtKeyFunc methdo to check the signing method 68 | func jwtKeyFunc(t *jwt.Token) (interface{}, error) { 69 | if t.Method.Alg() != JWTSigningMethod { 70 | return nil, fmt.Errorf("jwt: unexpected signing method '%v'", t.Header["alg"]) 71 | } 72 | return JWTSigningKey, nil 73 | } 74 | -------------------------------------------------------------------------------- /rest-api-jwt-auth/config/env/dev.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Development Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | dev { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Log Configuration 9 | # 10 | # Doc: https://docs.aahframework.org/logging.html 11 | # Doc: https://docs.aahframework.org/log-config.html 12 | # ----------------------------------------------------------------------------- 13 | log { 14 | receiver = "console" 15 | level = "debug" 16 | format = "text" 17 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 18 | color = true 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /rest-api-jwt-auth/config/env/prod.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Production Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | prod { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Runtime configuration 9 | # Doc: https://docs.aahframework.org/app-config.html#section-runtime 10 | # ----------------------------------------------------------------------------- 11 | runtime { 12 | debug { 13 | strip_src_base = true 14 | } 15 | } 16 | 17 | # ----------------------------------------------------------------------------- 18 | # Log Configuration 19 | # 20 | # Doc: https://docs.aahframework.org/logging.html 21 | # Doc: https://docs.aahframework.org/log-config.html 22 | # ----------------------------------------------------------------------------- 23 | log { 24 | receiver = "file" 25 | file = "rest-api-jwt-auth.log" 26 | level = "warn" 27 | format = "text" 28 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 29 | color = false 30 | rotate { 31 | policy = "daily" 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /rest-api-jwt-auth/config/routes.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # rest-api-jwt-auth - Application Routes Configuration 3 | # 4 | # Refer documentation to explore and configure routes. 5 | # Doc: https://docs.aahframework.org/routing.html 6 | # ----------------------------------------------------------------------------- 7 | 8 | domains { 9 | #------------------------------------------------------------------------------ 10 | # Domain/subdomain Key Name 11 | # Choose an `unique keyname` to define domain section and its configuration. 12 | # Tip: domain name address, port no values to create a domain key, etc. 13 | # 14 | # Doc: https://docs.aahframework.org/routes-config.html#domain-configuration 15 | #------------------------------------------------------------------------------ 16 | localhost { 17 | name = "rest-api-jwt-auth routes" 18 | host = "localhost" 19 | default_auth = "jwt_auth" 20 | 21 | # ----------------------------------------------------------------------------- 22 | # Routes Configuration 23 | # 24 | # Doc: https://docs.aahframework.org/routes-config.html#routes-configuration 25 | # ----------------------------------------------------------------------------- 26 | routes { 27 | index { 28 | path = "/" 29 | controller = "AppController" 30 | auth = "anonymous" 31 | } 32 | 33 | v1_group { 34 | path = "/v1" 35 | 36 | routes { 37 | login { 38 | path = "/token" 39 | method = "POST" 40 | controller = "AppController" 41 | action = "Token" 42 | auth = "anonymous" 43 | } 44 | 45 | reportee_info { 46 | path = "/reportee/:email" 47 | controller = "InfoController" 48 | action = "ReporteeInfo" 49 | authorization { 50 | satisfy = "both" 51 | roles = [ 52 | "hasrole(manager)" 53 | ] 54 | permissions = [ 55 | "ispermitted(user:read:reportee)" 56 | ] 57 | } 58 | } 59 | } 60 | } 61 | 62 | } # end - routes 63 | 64 | } # end - localhost 65 | 66 | } # end - domains 67 | -------------------------------------------------------------------------------- /rest-api-jwt-auth/config/security.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # rest-api-jwt-auth - Application Security Configurations 3 | # 4 | # Refer documentation to explore and customize the configurations. 5 | # Doc: https://docs.aahframework.org/security-config.html 6 | # ----------------------------------------------------------------------------- 7 | security { 8 | 9 | # ----------------------------------------------------------------------------- 10 | # Auth Schemes configuration 11 | # Doc: https://docs.aahframework.org/authentication.html 12 | # ----------------------------------------------------------------------------- 13 | auth_schemes { 14 | 15 | # ----------------------------------------------------------------------------- 16 | # Generic auth scheme 17 | # Choose a unique key name. It gets used as route auth. 18 | # 19 | # Doc: https://docs.aahframework.org/auth-schemes/generic.html 20 | # ----------------------------------------------------------------------------- 21 | jwt_auth { 22 | scheme = "generic" 23 | authenticator = "security/AuthenticationProvider" 24 | authorizer = "security/AuthorizationProvider" 25 | 26 | # JWT configuration - Signing key and method 27 | sign { 28 | key = "5440b995f33446bb8b17a06e65eaa7597f2c4b181aac46929dcf8025d608b1a1" 29 | method = "HS256" 30 | } 31 | } 32 | } 33 | 34 | # --------------------------------------------------------------------------- 35 | # HTTP Secure Header(s) 36 | # Application security headers with many safe defaults. 37 | # Doc: https://docs.aahframework.org/security-config.html#section-http-header 38 | # 39 | # Tip: Quick way to verify secure headers - https://securityheaders.io 40 | # --------------------------------------------------------------------------- 41 | http_header { 42 | enable = true 43 | xxssp = "" 44 | xfo = "DENY" 45 | rp = "" 46 | xpcdp = "" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /rest-api-jwt-auth/go.mod: -------------------------------------------------------------------------------- 1 | module aahframework.org/examples/rest-api-jwt-auth 2 | 3 | require ( 4 | aahframe.work v0.12.2 5 | github.com/dgrijalva/jwt-go v3.2.0+incompatible 6 | golang.org/x/crypto v0.0.0-20181012144002-a92615f3c490 7 | ) 8 | -------------------------------------------------------------------------------- /rest-api/.gitignore: -------------------------------------------------------------------------------- 1 | # aah framework application - .gitignore 2 | 3 | aah.go 4 | *.pid 5 | build/ 6 | aah_*_vfs.go 7 | app/generated 8 | # aah application - end 9 | vendor/*/ 10 | 11 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 12 | *.o 13 | *.a 14 | *.so 15 | 16 | # Folders 17 | _obj 18 | _test 19 | 20 | # Architecture specific extensions/prefixes 21 | *.[568vq] 22 | [568vq].out 23 | 24 | *.cgo1.go 25 | *.cgo2.c 26 | _cgo_defun.c 27 | _cgo_gotypes.go 28 | _cgo_export.* 29 | 30 | _testmain.go 31 | 32 | *.exe 33 | *.test 34 | *.prof 35 | -------------------------------------------------------------------------------- /rest-api/app/controllers/app.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package controllers 6 | 7 | import ( 8 | "aahframe.work" 9 | "aahframework.org/examples/rest-api/app/models" 10 | ) 11 | 12 | // AppController struct application controller 13 | type AppController struct { 14 | *aah.Context 15 | } 16 | 17 | // Index method is application root API endpoint. 18 | func (c *AppController) Index() { 19 | c.Reply().Ok().JSON(models.Greet{ 20 | Message: "Welcome to aah framework - REST API Services example", 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /rest-api/app/controllers/post.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package controllers 6 | 7 | import ( 8 | "fmt" 9 | 10 | "aahframe.work" 11 | "aahframework.org/examples/rest-api/app/models" 12 | ) 13 | 14 | // PostController implements the post APi endpoints. 15 | type PostController struct { 16 | *aah.Context 17 | } 18 | 19 | // List method returns all the posts available. 20 | func (c *PostController) List() { 21 | posts := models.AllPosts() 22 | c.Log().Infof("%v posts found", len(posts)) 23 | c.Reply().JSON(aah.Data{ 24 | "posts": posts, 25 | }) 26 | } 27 | 28 | // Create method to create a post via JSON. 29 | func (c *PostController) Create(post *models.Post) { 30 | c.Log().Infof("Post Info: %+v", *post) 31 | id := models.CreatePost(post) 32 | newResourceURL := fmt.Sprintf("%s:%v", c.Req.Scheme, c.RouteURL("retrieve_post", id)) 33 | c.Reply().Created(). 34 | Header("Location", newResourceURL). 35 | JSON(aah.Data{ 36 | "id": id, 37 | }) 38 | } 39 | 40 | // Retrieve method retunrs single post details for given post ID. 41 | func (c *PostController) Retrieve(id int64) { 42 | c.Log().Infof("Retrieving post, ID: %v", id) 43 | post, err := models.GetPost(id) 44 | if err != nil { 45 | c.Log().Errorf("Post ID %v, %v", id, err) 46 | c.Reply().NotFound().JSON(aah.Data{ 47 | "error": err.Error(), 48 | }) 49 | return 50 | } 51 | 52 | c.Reply().JSON(models.ToPostAlias(post)) 53 | } 54 | 55 | // Update method updates the post with given content. 56 | func (c *PostController) Update(id int64, post *models.Post) { 57 | c.Log().Infof("Updating post: %v", id) 58 | if post.ID == 0 { 59 | post.ID = id 60 | } 61 | 62 | if err := models.UpdatePost(post); err != nil { 63 | c.Log().Errorf("Post ID %v, %v", id, err) 64 | c.Reply().NotFound().JSON(aah.Data{ 65 | "error": err.Error(), 66 | }) 67 | return 68 | } 69 | 70 | c.Reply().NoContent() 71 | } 72 | 73 | // Delete method deletes the post of given post ID. 74 | func (c *PostController) Delete(id int64) { 75 | c.Log().Infof("Deleting post, ID: %v", id) 76 | if err := models.DeletePost(id); err != nil { 77 | c.Log().Errorf("Post ID %v, %v", id, err) 78 | c.Reply().NotFound().JSON(aah.Data{ 79 | "error": err.Error(), 80 | }) 81 | return 82 | } 83 | 84 | c.Reply().NoContent() 85 | } 86 | -------------------------------------------------------------------------------- /rest-api/app/models/greet.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jeevanandam M. (https://github.com/jeevatkm) 2 | // aahframework.org/examples source code and usage is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package models 6 | 7 | // Greet holds the greeting message. 8 | type Greet struct { 9 | Message string `json:"message"` 10 | } 11 | -------------------------------------------------------------------------------- /rest-api/config/env/dev.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Development Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | dev { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Log Configuration 9 | # 10 | # Doc: https://docs.aahframework.org/logging.html 11 | # Doc: https://docs.aahframework.org/log-config.html 12 | # ----------------------------------------------------------------------------- 13 | log { 14 | receiver = "console" 15 | level = "debug" 16 | format = "text" 17 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 18 | color = true 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /rest-api/config/env/prod.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Production Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | prod { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Runtime configuration 9 | # Doc: https://docs.aahframework.org/app-config.html#section-runtime 10 | # ----------------------------------------------------------------------------- 11 | runtime { 12 | debug { 13 | strip_src_base = true 14 | } 15 | } 16 | 17 | # ----------------------------------------------------------------------------- 18 | # Log Configuration 19 | # 20 | # Doc: https://docs.aahframework.org/logging.html 21 | # Doc: https://docs.aahframework.org/log-config.html 22 | # ----------------------------------------------------------------------------- 23 | log { 24 | receiver = "file" 25 | file = "rest-api.log" 26 | level = "warn" 27 | format = "text" 28 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 29 | color = false 30 | rotate { 31 | policy = "daily" 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /rest-api/config/routes.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # rest-api - Application Routes Configuration 3 | # 4 | # Refer documentation to explore and configure routes. 5 | # Doc: https://docs.aahframework.org/routing.html 6 | # ----------------------------------------------------------------------------- 7 | 8 | domains { 9 | #------------------------------------------------------------------------------ 10 | # Domain/subdomain Key Name 11 | # Choose an `unique keyname` to define domain section and its configuration. 12 | # Tip: domain name address, port no values to create a domain key, etc. 13 | # 14 | # Doc: https://docs.aahframework.org/routes-config.html#domain-configuration 15 | #------------------------------------------------------------------------------ 16 | localhost { 17 | name = "rest-api routes" 18 | host = "localhost" 19 | 20 | # ----------------------------------------------------------------------------- 21 | # Routes Configuration 22 | # 23 | # Doc: https://docs.aahframework.org/routes-config.html#routes-configuration 24 | # ----------------------------------------------------------------------------- 25 | routes { 26 | index { 27 | path = "/" 28 | controller = "AppController" 29 | } 30 | 31 | # Demonstrating nested/namespace/group routes 32 | v1_api { 33 | path = "/v1" 34 | 35 | # Child routes of "/v1/*" 36 | routes { 37 | list_posts { 38 | path = "/posts" 39 | controller = "PostController" 40 | action = "List" 41 | 42 | routes { 43 | create_post { 44 | method = "POST" 45 | } 46 | retrieve_post { 47 | path = "/:id" 48 | action = "Retrieve" 49 | 50 | routes { 51 | update_post { 52 | method = "PUT" 53 | } 54 | delete_post { 55 | method = "DELETE" 56 | } 57 | } 58 | } 59 | } 60 | } 61 | 62 | } # end - Child routes of "/v1/*" 63 | 64 | } # end - v1 API 65 | 66 | } # end - routes 67 | 68 | } # end - localhost 69 | 70 | } # end - domains 71 | -------------------------------------------------------------------------------- /rest-api/config/security.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # rest-api - Application Security Configuration 3 | # 4 | # Refer documentation to explore and customize the configurations. 5 | # Doc: https://docs.aahframework.org/security-config.html 6 | # ----------------------------------------------------------------------------- 7 | 8 | security { 9 | 10 | # --------------------------------------------------------------------------- 11 | # HTTP Secure Header(s) 12 | # Application security headers with many safe defaults. 13 | # Doc: https://docs.aahframework.org/security-config.html#section-http-header 14 | # 15 | # Tip: Quick way to verify secure headers - https://securityheaders.io 16 | # --------------------------------------------------------------------------- 17 | http_header { 18 | enable = true 19 | xxssp = "" 20 | xfo = "DENY" 21 | rp = "" 22 | xpcdp = "" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /rest-api/go.mod: -------------------------------------------------------------------------------- 1 | module aahframework.org/examples/rest-api 2 | 3 | require aahframe.work v0.12.2 4 | -------------------------------------------------------------------------------- /simple-chat/.gitignore: -------------------------------------------------------------------------------- 1 | # aah application - .gitignore 2 | 3 | aah.go 4 | *.pid 5 | build/ 6 | aah_*_vfs.go 7 | app/generated 8 | # aah application - end 9 | vendor/*/ 10 | 11 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 12 | *.o 13 | *.a 14 | *.so 15 | 16 | # Folders 17 | _obj 18 | _test 19 | 20 | # Architecture specific extensions/prefixes 21 | *.[568vq] 22 | [568vq].out 23 | 24 | *.cgo1.go 25 | *.cgo2.c 26 | _cgo_defun.c 27 | _cgo_gotypes.go 28 | _cgo_export.* 29 | 30 | _testmain.go 31 | 32 | *.exe 33 | *.test 34 | *.prof 35 | -------------------------------------------------------------------------------- /simple-chat/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

Example - Simple Chat

4 |

5 | 6 | This example shows WebSocket implementation with aah framework. It does reading and replying text with WS client. aah WebSocket also covers the basis of subscribing to WebSocket aah server events. 7 | 8 | Learn more about [aah WebSocket](https://docs.aahframework.org/websocket.html) 9 | 10 | ### Get aah examples 11 | 12 | ```bash 13 | git clone https://github.com/go-aah/examples.git aah-examples 14 | ``` 15 | 16 | ### Run this example 17 | 18 | ```bash 19 | cd aah-examples/simple-chat 20 | aah run 21 | ``` 22 | 23 | ### Visit this URL 24 | 25 | * http://localhost:8080 26 | 27 | Go to application home page, click the button "Let's chat". 28 | -------------------------------------------------------------------------------- /simple-chat/app/controllers/app.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "aahframe.work" 5 | ) 6 | 7 | // AppController struct application controller 8 | type AppController struct { 9 | *aah.Context 10 | } 11 | 12 | // Index method is application home page. 13 | func (c *AppController) Index() { 14 | 15 | } 16 | 17 | // SimpleChatDemo method is show a chat page. 18 | func (c *AppController) SimpleChatDemo() { 19 | 20 | } 21 | -------------------------------------------------------------------------------- /simple-chat/app/websockets/event.go: -------------------------------------------------------------------------------- 1 | package websockets 2 | 3 | import "aahframe.work/ws" 4 | 5 | // HandleEvents method is to demostrate aah WebSocket events published for each 6 | // WebSocket connection made to aah server and its life cycle. 7 | func HandleEvents(eventName string, ctx *ws.Context) { 8 | switch eventName { 9 | case ws.EventOnPreConnect: 10 | ctx.Log().Infof("I'm %s event", eventName) 11 | case ws.EventOnPostConnect: 12 | ctx.Log().Infof("I'm %s event", eventName) 13 | // aah assigns unique ID for each WebSocket Request. 14 | // Unique ID generated using MongoDB Object ID algrothim. 15 | _ = ctx.ReplyText("Greetings from Server!") 16 | _ = ctx.ReplyText("Just letting you know, your ID: " + ctx.Req.ID) 17 | case ws.EventOnPostDisconnect: 18 | ctx.Log().Infof("I'm %s event", eventName) 19 | ctx.Log().Info("WebSocket client disconnected") 20 | case ws.EventOnError: 21 | ctx.Log().Infof("I'm %s event", eventName) 22 | ctx.Log().Errorf("Ooh no! error occurred: %s", ctx.ErrorReason()) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /simple-chat/app/websockets/simple_chat.go: -------------------------------------------------------------------------------- 1 | package websockets 2 | 3 | import ( 4 | "html" 5 | 6 | "aahframe.work/ws" 7 | ) 8 | 9 | // SimpleChatWebSocket hold simple chat implementation. 10 | type SimpleChatWebSocket struct { 11 | *ws.Context 12 | } 13 | 14 | // SimpleChat method recevies chat text from chat client and echo's 15 | // back to them and logs on server side. 16 | // 17 | // Route: /simple-chat 18 | // Method: WS 19 | func (w *SimpleChatWebSocket) SimpleChat() { 20 | for { 21 | text, err := w.ReadText() 22 | if err != nil { 23 | if ws.IsDisconnected(err) { 24 | // WebSocket client is gone, exit here 25 | return 26 | } 27 | 28 | w.Log().Error(err) 29 | continue // we are moving on to next WS frame/msg 30 | } 31 | 32 | w.Log().Info("Received from client: ", text) 33 | 34 | // if no error, echo back the Text to WebSocket client 35 | if err = w.ReplyText(html.UnescapeString(text)); err != nil { 36 | w.Log().Error(err) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /simple-chat/config/env/dev.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Development Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | dev { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Log Configuration 9 | # 10 | # Doc: https://docs.aahframework.org/logging.html 11 | # Doc: https://docs.aahframework.org/log-config.html 12 | # ----------------------------------------------------------------------------- 13 | log { 14 | receiver = "console" 15 | level = "debug" 16 | format = "text" 17 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 18 | color = true 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /simple-chat/config/env/prod.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Production Configuration 3 | # ----------------------------------------------------------------------------- 4 | 5 | prod { 6 | 7 | # ----------------------------------------------------------------------------- 8 | # Runtime configuration 9 | # Doc: https://docs.aahframework.org/app-config.html#section-runtime 10 | # ----------------------------------------------------------------------------- 11 | runtime { 12 | debug { 13 | strip_src_base = true 14 | } 15 | } 16 | 17 | # ----------------------------------------------------------------------------- 18 | # Log Configuration 19 | # 20 | # Doc: https://docs.aahframework.org/logging.html 21 | # Doc: https://docs.aahframework.org/log-config.html 22 | # ----------------------------------------------------------------------------- 23 | log { 24 | receiver = "file" 25 | file = "simple-chat.log" 26 | level = "warn" 27 | format = "text" 28 | pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields" 29 | color = false 30 | rotate { 31 | policy = "daily" 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /simple-chat/config/security.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # simple-chat - Application Security Configuration 3 | # 4 | # Refer documentation to explore and customize the configurations. 5 | # Doc: https://docs.aahframework.org/security-config.html 6 | # ----------------------------------------------------------------------------- 7 | 8 | security { 9 | 10 | # ----------------------------------------------------------------------------- 11 | # Anti-CSRF (Cross Site Request Forgery protection) 12 | # 13 | # Doc: https://docs.aahframework.org/anti-csrf-protection.html 14 | # ----------------------------------------------------------------------------- 15 | anti_csrf { 16 | enable = true 17 | sign_key = "37ace3d31a53358b2f17564c9f148e7618d587e94ab3f3f48684ebd90c0da40b" 18 | enc_key = "db9aaa2abd6aaf1ae65e8acfabc6e815" 19 | } 20 | 21 | # --------------------------------------------------------------------------- 22 | # HTTP Secure Header(s) 23 | # Application security headers with many safe defaults. 24 | # 25 | # Doc: https://docs.aahframework.org/security-config.html#section-http-header 26 | # 27 | # Tip: Quick way to verify secure headers - https://securityheaders.io 28 | # --------------------------------------------------------------------------- 29 | http_header { 30 | enable = true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /simple-chat/go.mod: -------------------------------------------------------------------------------- 1 | module aahframework.org/examples/simple-chat 2 | 3 | require ( 4 | aahframe.work v0.12.2 5 | aahframe.work/minify/html v0.2.0 6 | ) 7 | -------------------------------------------------------------------------------- /simple-chat/i18n/messages.en: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # i18n messages for simple-chat application 3 | # 4 | # Doc: https://docs.aahframework.org/i18n.html 5 | # --------------------------------------------------------------------------- 6 | 7 | # This structure is example purpose 8 | # So choose your suitable structure for your application 9 | label { 10 | pages { 11 | app { 12 | index { 13 | title = "Simple Chat Home - aah Go web framework" 14 | } 15 | chat_demo { 16 | title = "Simple Chat Demo Page - aah Go web framework" 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /simple-chat/static/css/aah.css: -------------------------------------------------------------------------------- 1 | /* 2 | Minimal aah framework application template CSS. 3 | Based on your need choose your CSS framework. 4 | */ 5 | 6 | html { 7 | font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; 8 | -webkit-text-size-adjust: 100%; 9 | -ms-text-size-adjust: 100%; 10 | } 11 | 12 | * { margin: 0; padding: 0; box-sizing: border-box; } 13 | 14 | .header { 15 | overflow: hidden; 16 | top: 0; 17 | width: 100%; 18 | height: 65px; 19 | border-bottom: 1px #757575 solid; 20 | } 21 | 22 | .header h2 { 23 | padding-left: 80px; 24 | margin-top: -50px; 25 | } 26 | 27 | form { 28 | background: #959595; 29 | padding: 3px; 30 | position: fixed; 31 | bottom: 0; 32 | width: 100%; 33 | } 34 | 35 | form input { 36 | border: 0; 37 | padding: 10px; 38 | width: 90%; 39 | margin-right: .5%; 40 | font-size: 14px; 41 | } 42 | 43 | form button { 44 | color: #fff; 45 | font-weight: 500; 46 | font-size: 1em; 47 | width: 9%; 48 | background: #3857ba; 49 | border: none; 50 | padding: 10px; 51 | } 52 | 53 | .chat-messages { 54 | list-style-type: none; 55 | margin: 0; 56 | padding: 0; 57 | } 58 | 59 | .chat-messages li { 60 | padding: 5px 10px; 61 | } 62 | 63 | .chat-messages li:nth-child(odd) { 64 | background: #eee; 65 | } 66 | 67 | .chat-status { 68 | float: right; 69 | padding-right: 25px; 70 | font-size: 1em; 71 | margin-top: -25px; 72 | } 73 | 74 | .container { 75 | padding-right: 15px; 76 | padding-left: 15px; 77 | margin-right: auto; 78 | margin-left: auto; 79 | } 80 | @media (min-width: 992px) { 81 | .container { 82 | width: 970px; 83 | } 84 | } 85 | @media (min-width: 1200px) { 86 | .container { 87 | width: 1170px; 88 | } 89 | } 90 | 91 | .row { 92 | margin-right: -15px; 93 | margin-left: -15px; 94 | } 95 | 96 | .text-center { 97 | text-align: center; 98 | } 99 | 100 | .welcome-msg { 101 | padding-top: 30px; 102 | padding-bottom: 30px; 103 | margin-bottom: 20px; 104 | color: inherit; 105 | } 106 | 107 | #showcases ul li { 108 | font-size: 1.15em; 109 | } 110 | -------------------------------------------------------------------------------- /simple-chat/static/img/aah-framework-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/simple-chat/static/img/aah-framework-logo.png -------------------------------------------------------------------------------- /simple-chat/static/img/aah-logo-64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/simple-chat/static/img/aah-logo-64x64.png -------------------------------------------------------------------------------- /simple-chat/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-aah/examples/f68c749b4625fe73e114045f3031968f61001a92/simple-chat/static/img/favicon.ico -------------------------------------------------------------------------------- /simple-chat/static/js/aah.js: -------------------------------------------------------------------------------- 1 | // JS for Simple Chat 2 | 3 | function byId(id) { 4 | return document.getElementById(id); 5 | } 6 | 7 | // http://youmightnotneedjquery.com/#on 8 | function on(id, en, fn) { 9 | var obj = byId(id); 10 | if (obj.attachEvent) { 11 | obj.attachEvent(en, fn); 12 | } else { 13 | obj.addEventListener(en, fn); 14 | } 15 | } 16 | 17 | function addChatMsg(msg) { 18 | var li = document.createElement('li'); 19 | li.appendChild(document.createTextNode(msg)); 20 | byId('chatMessages').appendChild(li); 21 | } 22 | 23 | function connectWebSocket(uri) { 24 | var chatSocket = new WebSocket(uri); 25 | 26 | chatSocket.onopen = function (e) { 27 | byId('chatStatus').innerHTML = 'Connected: ' + uri; 28 | byId('chatStatus').style.color = 'green'; 29 | } 30 | 31 | chatSocket.onmessage = function (e) { 32 | addChatMsg(e.data); 33 | } 34 | 35 | chatSocket.onclose = function (e) { 36 | byId('chatStatus').innerHTML = 'Disconnected: ' + uri; 37 | byId('chatStatus').style.color = 'red'; 38 | } 39 | 40 | chatSocket.onerror = function (e) { 41 | console.log(e); 42 | } 43 | 44 | return chatSocket; 45 | } 46 | -------------------------------------------------------------------------------- /simple-chat/static/robots.txt: -------------------------------------------------------------------------------- 1 | # Prevents all robots visiting your site. 2 | User-agent: * 3 | Disallow: / 4 | -------------------------------------------------------------------------------- /simple-chat/views/common/error_footer.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /simple-chat/views/common/error_header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ .Error.Code }} {{ .Error.Message }} 6 | 7 | 8 | 34 | 35 | -------------------------------------------------------------------------------- /simple-chat/views/common/footer_scripts.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /simple-chat/views/common/head_tags.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /simple-chat/views/errors/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ include "/common/error_header.html" . -}} 4 | 5 |
{{ with .Error }} 6 |
7 |
8 | {{ .Code }} {{ .Message }} 9 |
10 |
{{ end }} 11 |
12 | {{ include "/common/error_footer.html" . -}} 13 | 14 | 15 | -------------------------------------------------------------------------------- /simple-chat/views/errors/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ include "/common/error_header.html" . -}} 4 | 5 |
{{ with .Error }} 6 |
7 |
8 | {{ .Code }} {{ .Message }} 9 |
10 |
{{ end }} 11 |
12 | {{ include "/common/error_footer.html" . -}} 13 | 14 | 15 | -------------------------------------------------------------------------------- /simple-chat/views/layouts/master.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ template "title" . }} 8 | {{ include "/common/head_tags.html" . }} 9 | 10 | 11 | {{ template "body" . -}} 12 | {{ include "/common/footer_scripts.html" . }} 13 | 14 | 15 | -------------------------------------------------------------------------------- /simple-chat/views/pages/app/index.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | {{ i18n . "label.pages.app.index.title" }} 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 |
7 |
8 | aah framework logo 9 |

Welcome to aah framework - WebSocket Example

10 |

Simple Chat

11 |
12 |
13 |
14 |

This example application showcases:

15 |
16 |
17 |
    18 |
  • Reading Text from WebSocket client
  • 19 |
  • Replying Text to WebSocket client
  • 20 |
  • Basis of Subscribing to WebSocket events
  • 21 |
22 |
23 |

24 | Let's chat 😊 25 |
26 |
27 |
28 | {{- end }} 29 | -------------------------------------------------------------------------------- /simple-chat/views/pages/app/simplechatdemo.html: -------------------------------------------------------------------------------- 1 | {{ define "title" -}} 2 | {{ i18n . "label.pages.app.chat_demo.title" }} 3 | {{- end }} 4 | 5 | {{ define "body" -}} 6 |
7 | 8 | aah logo 9 | 10 |

Simple Chat

11 |
12 |
13 | 14 |
15 | 16 |
17 | 37 | {{- end }} 38 | --------------------------------------------------------------------------------