فهرست منبع

Add registation forms

- Add registration enable option
- Add basig registration forms
- Fix few template issues
Alexey Edelev 5 سال پیش
والد
کامیت
473e32d022
11فایلهای تغییر یافته به همراه174 افزوده شده و 24 حذف شده
  1. 21 16
      config/config.go
  2. 4 1
      config/main.ini.default
  3. 0 0
      web/assets/eye.svg
  4. 26 1
      web/css/controls.css
  5. 1 0
      web/css/styles.css
  6. 31 1
      web/server.go
  7. 24 0
      web/templater.go
  8. 7 3
      web/templates/error.html
  9. 3 2
      web/templates/login.html
  10. 56 0
      web/templates/register.html
  11. 1 0
      web/templates/signup.html

+ 21 - 16
config/config.go

@@ -44,6 +44,7 @@ const (
 	KeyAttachmentsPath     = "attachments_path"
 	KeyAttachmentsUser     = "attachments_user"
 	KeyAttachmentsPassword = "attachments_password"
+	KeyRegistrationEnabled = "registration_enabled"
 )
 
 const (
@@ -70,14 +71,15 @@ func ConfigInstance() *GostfixConfig {
 }
 
 type gostfixConfig struct {
-	MyDomain        string
-	VMailboxMaps    string
-	VMailboxBase    string
-	VMailboxDomains []string
-	MongoUser       string
-	MongoPassword   string
-	MongoAddress    string
-	AttachmentsPath string
+	MyDomain            string
+	VMailboxMaps        string
+	VMailboxBase        string
+	VMailboxDomains     []string
+	MongoUser           string
+	MongoPassword       string
+	MongoAddress        string
+	AttachmentsPath     string
+	RegistrationEnabled bool
 }
 
 func newConfig() (config *gostfixConfig, err error) {
@@ -157,15 +159,18 @@ func newConfig() (config *gostfixConfig, err error) {
 		attachmentsPath = "attachments"
 	}
 
+	registrationEnabled := cfg.Section("").Key(KeyRegistrationEnabled).String()
+
 	config = &gostfixConfig{
-		MyDomain:        myDomain,
-		VMailboxBase:    baseDir,
-		VMailboxMaps:    mapsList[1],
-		VMailboxDomains: validDomains,
-		MongoUser:       mongoUser,
-		MongoPassword:   mongoPassword,
-		MongoAddress:    mongoAddress,
-		AttachmentsPath: attachmentsPath,
+		MyDomain:            myDomain,
+		VMailboxBase:        baseDir,
+		VMailboxMaps:        mapsList[1],
+		VMailboxDomains:     validDomains,
+		MongoUser:           mongoUser,
+		MongoPassword:       mongoPassword,
+		MongoAddress:        mongoAddress,
+		AttachmentsPath:     attachmentsPath,
+		RegistrationEnabled: registrationEnabled == "true",
 	}
 	return
 }

+ 4 - 1
config/main.ini.default

@@ -16,4 +16,7 @@ mongo_user =
 mongo_password =
 
 # Path to attachments storage. By dafault "./attachments".
-attachments_path = attachments
+attachments_path = attachments
+
+# Enables registration functionality, disabled by default
+registration_enabled = false

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
web/assets/eye.svg


+ 26 - 1
web/css/controls.css

@@ -137,6 +137,15 @@
     -webkit-transition: 0.2s ease all;
 }
 
+.inpt img {
+    position: absolute;
+    right: 10px;
+    top: 14px;
+    display: block;
+    width: 24px;
+    height: 24px;
+}
+
 .inpt input:focus ~ label {
     top: -25px;
     font-size: var(--normal-text-size);
@@ -154,13 +163,21 @@
     width: 100%;
 }
 
+.inpt.bad .bar:before, .inpt.bad .bar:after{
+    background-color: var(--bad-color);
+}
+
+.inpt.weak .bar:before, .inpt.weak .bar:after{
+    background-color: var(--invalid-color);
+}
+
 .inpt .bar:before, .bar:after {
     content: '';
     height: 2px;
     width: 0;
     bottom: 0;
     position: absolute;
-    background: var(--primary-color);
+    background-color: var(--primary-color);
     transition: 0.2s ease all;
     -moz-transition: 0.2s ease all;
     -webkit-transition: 0.2s ease all;
@@ -194,6 +211,14 @@
     animation:inputHighlighter 0.3s ease;
 }
 
+.inpt.bad input{
+    border-bottom: 1px solid var(--bad-color);
+}
+
+.inpt.weak input{
+    border-bottom: 1px solid var(--invalid-color);
+}
+
 @-webkit-keyframes inputHighlighter {
     from { background: var(--secondary-color); }
     to { width:0; background:transparent; }

+ 1 - 0
web/css/styles.css

@@ -16,6 +16,7 @@
     --secondary-text-dark-color: #666666;
     --default-radius: 5px;
     --invalid-color: #f0ad4e;
+    --bad-color: #c62d2a;
 
     --base-text-padding: 10px;
     --base-border-padding: 8px;

+ 31 - 1
web/server.go

@@ -27,12 +27,14 @@ package web
 
 import (
 	"fmt"
+	"html/template"
 	"log"
 	"net/http"
 	"strconv"
 
 	auth "git.semlanik.org/semlanik/gostfix/auth"
 	common "git.semlanik.org/semlanik/gostfix/common"
+	"git.semlanik.org/semlanik/gostfix/config"
 	db "git.semlanik.org/semlanik/gostfix/db"
 	utils "git.semlanik.org/semlanik/gostfix/utils"
 
@@ -121,6 +123,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 			s.handleLogin(w, r)
 		case "/logout":
 			s.handleLogout(w, r)
+		case "/register":
+			s.handleRegister(w, r)
 		case "/mail":
 			fallthrough
 		case "/setRead":
@@ -137,6 +141,24 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	}
 }
 
+func (s *Server) handleRegister(w http.ResponseWriter, r *http.Request) {
+	if !config.ConfigInstance().RegistrationEnabled {
+		s.error(http.StatusNotImplemented, "Registration is disabled on this server", w)
+		return
+	}
+
+	if err := r.ParseForm(); err == nil {
+		// user := r.FormValue("user")
+		// password := r.FormValue("password")
+		// fullname := r.FormValue("fullname")
+	}
+
+	fmt.Fprint(w, s.templater.ExecuteRegister(&struct {
+		Version string
+	}{common.Version}))
+
+}
+
 func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) {
 	//Check passed in form login/password pair first
 	if err := r.ParseForm(); err == nil {
@@ -155,11 +177,19 @@ func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	var signupTemplate template.HTML
+	if config.ConfigInstance().RegistrationEnabled {
+		signupTemplate = template.HTML(s.templater.ExecuteSignup(""))
+	} else {
+		signupTemplate = ""
+	}
+
 	//Otherwise make sure user logged out and show login page
 	s.logout(w, r)
 	fmt.Fprint(w, s.templater.ExecuteLogin(&struct {
 		Version string
-	}{common.Version}))
+		Signup  template.HTML
+	}{common.Version, signupTemplate}))
 }
 
 func (s *Server) handleLogout(w http.ResponseWriter, r *http.Request) {

+ 24 - 0
web/templater.go

@@ -42,6 +42,8 @@ const (
 	FoldersTemplateName    = "folders.html"
 	MailNewTemplateName    = "mailnew.html"
 	MailTemplateName       = "mailTemplate.eml"
+	SignupTemplateName     = "signup.html"
+	RegisterTemplateName   = "register.html"
 )
 
 type Templater struct {
@@ -50,6 +52,8 @@ type Templater struct {
 	detailsTemplate    *template.Template
 	errorTemplate      *template.Template
 	loginTemplate      *template.Template
+	signupTemplate     *template.Template
+	registerTemplate   *template.Template
 	statusLineTemplate *template.Template
 	foldersTemaplate   *template.Template
 	mailNewTemplate    *template.Template
@@ -103,6 +107,16 @@ func NewTemplater(templatesPath string) (t *Templater) {
 		log.Fatal(err)
 	}
 
+	signup, err := parseTemplate(templatesPath + "/" + SignupTemplateName)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	register, err := parseTemplate(templatesPath + "/" + RegisterTemplateName)
+	if err != nil {
+		log.Fatal(err)
+	}
+
 	t = &Templater{
 		indexTemplate:      index,
 		mailListTemplate:   maillist,
@@ -113,6 +127,8 @@ func NewTemplater(templatesPath string) (t *Templater) {
 		foldersTemaplate:   folders,
 		mailNewTemplate:    mailNew,
 		mailTemplate:       mail,
+		signupTemplate:     signup,
+		registerTemplate:   register,
 	}
 	return
 }
@@ -146,6 +162,14 @@ func (t *Templater) ExecuteLogin(data interface{}) string {
 	return executeTemplateCommon(t.loginTemplate, data)
 }
 
+func (t *Templater) ExecuteSignup(data interface{}) string {
+	return executeTemplateCommon(t.signupTemplate, data)
+}
+
+func (t *Templater) ExecuteRegister(data interface{}) string {
+	return executeTemplateCommon(t.registerTemplate, data)
+}
+
 func (t *Templater) ExecuteStatusLine(data interface{}) string {
 	return executeTemplateCommon(t.statusLineTemplate, data)
 }

+ 7 - 3
web/templates/error.html

@@ -14,9 +14,13 @@
         <div id="main">
             <div class="horizontalPaddingBox">
                 <div style="display: flex; width: 100%; height: 100%; justify-content: center;">
-                    <img src="/assets/error.svg" height="100px"/>
-                    <span style="font-size: 26px;">{{.Code}}</span></br>
-                    <span style="font-size: var(--big-text-size);">{{.Text}}</span>
+                    <div style="margin: auto; display: flex; flex-direction: row;">
+                        <img src="/assets/error.svg" height="100px"/>
+                        <div style="display: flex; flex-direction: column;">
+                            <span style="font-size: 26px;">{{.Code}}</span></br>
+                            <span style="font-size: var(--big-text-size);">{{.Text}}</span>
+                        </div>
+                    </div>
                 </div>
             </div>
             <div id="copyrightBox" class="elidedText"><img src="/assets/logo.svg" height="30px"/>gostfix {{.Version}} Web interface. Copyright (c) 2020 Alexey Edelev &lt;semlanik@gmail.com&gt;</div>

+ 3 - 2
web/templates/login.html

@@ -13,8 +13,8 @@
     <body>
         <div id="main">
             <div class="horizontalPaddingBox" >
-                <div style="display: flex; width: 100%; height: 100%; justify-content: center;">
-                    <form method="POST" action="/login" style="margin: auto;">
+                <div style="display: flex; flex-direction: column; width: 100%; height: 100%; justify-content: center;">
+                    <form method="POST" action="/login" style="margin: 0 auto;">
                         <div class="inpt">
                             <input name="user" type="text" required>
                             <span class="highlight"></span>
@@ -29,6 +29,7 @@
                         </div>
                         <input type="submit" style="visibility: hidden;" />
                     </form>
+                    {{.Signup}}
                 </div>
             </div>
             <div id="copyrightBox" class="elidedText"><img src="/assets/logo.svg" height="30px"/>gostfix {{.Version}} Web interface. Copyright (c) 2020 Alexey Edelev &lt;semlanik@gmail.com&gt;</div>

+ 56 - 0
web/templates/register.html

@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8"/>
+        <link rel="icon" href="/assets/logo.png">
+        <link href="https://fonts.googleapis.com/css?family=Titillium+Web&display=swap" rel="stylesheet">
+        <link type="text/css" href="/css/index.css" rel="stylesheet">
+        <link type="text/css" href="/css/styles.css" rel="stylesheet">
+        <link type="text/css" href="/css/controls.css" rel="stylesheet">
+        <script src="/js/jquery-3.4.1.min.js"></script>
+        <script>
+            $(document).ready(function() {
+                $("#showPasswordButton").mousedown(function() {
+                    $("#passwordField").attr("type", "text")
+                })
+
+                $("#showPasswordButton").mouseup(function() {
+                    $("#passwordField").attr("type", "password")
+                })
+
+            })
+        </script>
+        <title>Gostfix mail {{.Version}}</title>
+    </head>
+    <body>
+        <div id="main">
+            <div class="horizontalPaddingBox">
+                <div style="display: flex; flex-direction: column; width: 100%; height: 100%; justify-content: center;">
+                    <form method="POST" action="/register" style="margin: 0 auto;">
+                        <div class="inpt bad">
+                            <input name="fullname" type="text" required>
+                            <span class="highlight"></span>
+                            <span class="bar"></span>
+                            <label>Full name</label>
+                        </div>
+                        <div class="inpt bad">
+                            <input name="user" type="text" required>
+                            <span class="highlight"></span>
+                            <span class="bar"></span>
+                            <label>Email</label>
+                        </div>
+                        <div class="inpt bad">
+                            <input id="passwordField" name="password" type="password" required>
+                            <span class="highlight"></span>
+                            <span class="bar"></span>
+                            <label>Password</label>
+                            <img id="showPasswordButton" src="/assets/eye.svg"/>
+                        </div>
+                        <input type="submit" style="visibility: hidden;" />
+                    </form>
+                </div>
+            </div>
+            <div id="copyrightBox" class="elidedText"><img src="/assets/logo.svg" height="30px"/>gostfix {{.Version}} Web interface. Copyright (c) 2020 Alexey Edelev &lt;semlanik@gmail.com&gt;</div>
+        </div>
+    </body>
+</html>

+ 1 - 0
web/templates/signup.html

@@ -0,0 +1 @@
+<a href="/register" style="color: var(--primary-color); font-size: var(--normal-text-size); margin: 0 auto">Sign up!</a>

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است