Skip to content

Commit

Permalink
added login and sqlite
Browse files Browse the repository at this point in the history
  • Loading branch information
LobbyLobster committed Oct 3, 2023
1 parent fe6cdad commit b2f39a1
Show file tree
Hide file tree
Showing 15 changed files with 390 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
tmp
imap-sync
LOG_imapsync
db.db
9 changes: 7 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ module imap-sync
go 1.21.0

require (
github.com/appleboy/gin-jwt/v2 v2.9.1
github.com/emersion/go-imap v1.2.1
github.com/gin-gonic/gin v1.9.1
github.com/lithammer/fuzzysearch v1.1.8
github.com/mattn/go-sqlite3 v1.14.17
github.com/sirupsen/logrus v1.9.3
golang.org/x/crypto v0.13.0
)

require github.com/go-session/session v3.1.2+incompatible // indirect

require (
github.com/bytedance/sonic v1.10.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
Expand All @@ -19,7 +24,9 @@ require (
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.15.4 // indirect
github.com/go-session/gin-session v3.1.0+incompatible
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang-jwt/jwt/v4 v4.4.3 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
Expand All @@ -33,11 +40,9 @@ require (
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/arch v0.5.0 // indirect
golang.org/x/crypto v0.13.0 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
58 changes: 58 additions & 0 deletions go.sum

Large diffs are not rendered by default.

15 changes: 14 additions & 1 deletion internal/admin.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
package internal

import "github.com/gin-gonic/gin"
import (
"net/http"

"github.com/gin-gonic/gin"
ginsession "github.com/go-session/gin-session"
)

func handleAdmin(ctx *gin.Context) {
store := ginsession.FromContext(ctx)
_, ok := store.Get("user")
if !ok {
// User is not logged in, redirect them to the login page
ctx.Redirect(http.StatusTemporaryRedirect, "/login")
return
}

ctx.HTML(200, "admin.html", nil)
}
52 changes: 52 additions & 0 deletions internal/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package internal

import (
"net/http"

"github.com/gin-gonic/gin"
ginsession "github.com/go-session/gin-session"
"golang.org/x/crypto/bcrypt"
)

type user struct {
Name string `json:"username"`
Password string `json:"password"`
}

func handleLogin(ctx *gin.Context) {
store := ginsession.FromContext(ctx)
_, ok := store.Get("user")
if ok {
// User is not logged in, redirect them to the login page
ctx.Redirect(http.StatusTemporaryRedirect, "/")
return
}
ctx.HTML(200, "login.html", nil)
}

func login(ctx *gin.Context) {
var data user
data.Name = ctx.PostForm("username")
data.Password = ctx.PostForm("password")

pass, err := getPassword(data.Name)
if err != nil {
ctx.IndentedJSON(http.StatusUnauthorized, gin.H{"message": "user not found"})
return
}

err = bcrypt.CompareHashAndPassword([]byte(pass), []byte(data.Password))
if err != nil {
ctx.IndentedJSON(http.StatusUnauthorized, gin.H{"message": "wrong password"})
return
}
store := ginsession.FromContext(ctx)

store.Set("user", data.Name)
if err := store.Save(); err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save session"})
return
}
ctx.Redirect(http.StatusMovedPermanently, "/admin")

}
102 changes: 102 additions & 0 deletions internal/db.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package internal

import (
"database/sql"
"errors"
"fmt"
"reflect"

_ "github.com/mattn/go-sqlite3"
"golang.org/x/crypto/bcrypt"
)

var db *sql.DB

func InitDb() error {
var err error
db, err = sql.Open("sqlite3", "./db.db")
if err != nil {
return err
}
defer db.Close()

initStmt := `
CREATE TABLE IF NOT EXISTS Users (
id INTEGER PRIMARY KEY,
username VARCHAR(64) NULL,
password VARCHAR(64) NULL
);
`
_, err = db.Exec(initStmt)
if err != nil {
return err
}

var exists bool
err = db.QueryRow("SELECT exists (SELECT 1 FROM users WHERE username = ?)", admin_name).Scan(&exists)
if err != nil {
return err
}

password, err := bcrypt.GenerateFromPassword([]byte(*admin_pass), 14)
if err != nil {
return err
}

if !exists {
_, err = db.Exec("INSERT INTO users(username, password) VALUES(?, ?)", admin_name, password)
if err != nil {
return err
}
} else {
dbPass, err := getPassword(*admin_name)
if err != nil {
return err
}
if !reflect.DeepEqual(password, []byte(dbPass)) {
changePassword(*admin_name, string(password))
}
}

return nil
}

func changePassword(username string, newPassword string) error {
var err error
db, err = sql.Open("sqlite3", "./db.db")
if err != nil {
return err
}
defer db.Close()

stmt, err := db.Prepare("UPDATE users SET password = ? WHERE username = ?")
if err != nil {
return err
}
defer stmt.Close()

_, err = stmt.Exec(newPassword, username)
if err != nil {
return err
}

return nil
}

func getPassword(username string) (string, error) {
var err error
db, err = sql.Open("sqlite3", "./db.db")
if err != nil {
return "", err
}
defer db.Close()
var password string
err = db.QueryRow("SELECT password FROM users WHERE username = ?", username).Scan(&password)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return "", fmt.Errorf("no user found with username %s", username)
}
return "", err
}
return password, nil
}
2 changes: 2 additions & 0 deletions internal/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import "flag"

var (
port = flag.String("port", "8080", "Port to listen on")
admin_name = flag.String("admin_name", "admin", "Admin username")
admin_pass = flag.String("admin_pass", "admin", "Admin password")
source_server = flag.String("source_server", "", "Source server")
source_account = flag.String("source_account", "", "Source account")
source_password = flag.String("source_password", "", "Source password")
Expand Down
12 changes: 12 additions & 0 deletions internal/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,32 @@ package internal

import (
"github.com/gin-gonic/gin"
ginsession "github.com/go-session/gin-session"
)

func InitServer() {
SetupLogger(log)

err := InitDb()
if err != nil {
log.Error(err)
}

gin.SetMode(gin.ReleaseMode)
router := gin.Default()

router.Use(ginsession.New())

router.LoadHTMLGlob("templates/*")

router.Static("/static", "./static/")

router.GET("/", handleRoot)
router.GET("/admin", handleAdmin)
router.GET("/favicon.ico", func(ctx *gin.Context) {
ctx.File("favicon.ico")
})
router.GET("/login", handleLogin)

go initQueue()
// API endpoints
Expand All @@ -25,6 +36,7 @@ func InitServer() {
router.GET("/api/pagination", handlePagination)
router.POST("/api/validate", handleValidate)
router.POST("/api/search", handleSearch)
router.POST("/auth/login", login)

log.Info("Server starting on http://localhost:" + *port)

Expand Down
1 change: 1 addition & 0 deletions static/css/styles.css

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions static/js/cdn.min.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions static/js/htmx.min.js

Large diffs are not rendered by default.

63 changes: 63 additions & 0 deletions static/js/tailwind.js

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions templates/admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>imapsync-web-admin</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/styles.css" />
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/htmx.[email protected]"
<link rel="stylesheet" href="/static/css/styles.css" />
<script src="/static/js/tailwind.js"></script>
<script src="/static/js/htmx.min.js"
integrity="sha384-xcuj3WpfgjlKF+FXhSQFQ0ZNr39ln+hwjN3npfM9VBnUskLolQAcN80McRIVOPuO"
crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
<script defer src="/static/js/cdn.min.js"></script>

<style>
html,
Expand Down
6 changes: 3 additions & 3 deletions templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>imapsync-web</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/styles.css" />
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/htmx.[email protected]"
<link rel="stylesheet" href="/static/css/styles.css" />
<script src="/static/js/tailwind.js"></script>
<script src="/static/js/htmx.min.js"
integrity="sha384-xcuj3WpfgjlKF+FXhSQFQ0ZNr39ln+hwjN3npfM9VBnUskLolQAcN80McRIVOPuO"
crossorigin="anonymous"></script>

Expand Down
65 changes: 65 additions & 0 deletions templates/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Login</title>
<style>
body {
font-family: Arial, Helvetica, sans-serif;
}
.container {
width: 300px;
padding: 16px;
background-color: white;
margin: 0 auto;
margin-top: 100px;
border: 1px solid black;
border-radius: 4px;
}
input[type="text"],
input[type="password"] {
width: 90%;
padding: 15px;
margin: 5px 0 22px 0;
display: inline-block;
border: none;
background: #f1f1f1;
}
button {
background-color: #4caf50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
cursor: pointer;
width: 100%;
opacity: 0.9;
}
button:hover {
opacity: 1;
}
</style>
</head>
<body>
<form action="/auth/login" method="post" class="container">
<label for="uname"><b>Username</b></label>
<input
type="text"
placeholder="Enter Username"
name="username"
required
/>

<label for="psw"><b>Password</b></label>
<input
type="password"
placeholder="Enter Password"
name="password"
required
/>

<button type="submit">Login</button>
</form>
</body>
</html>

0 comments on commit b2f39a1

Please sign in to comment.