rewrite time!!

This commit is contained in:
leah 2022-03-28 23:22:41 +01:00
parent d80ee751fe
commit a8de79ac50
12 changed files with 0 additions and 401 deletions

11
LICENSE
View File

@ -1,11 +0,0 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

View File

@ -1,29 +0,0 @@
# admin
quick little admin panel.
## todo
- [ ] respectable web ui
- [ ] signup form
- [ ] lots of db code
- [ ] gitea authentication
- [ ] pam auth (maube?)
- [ ] automatic user creaton/deletion
- [ ] resource usage dashboard
## how 2 build
you need to build the stylesheet with tailwind first:
```
npm i -g tailwindcss
npx tailwindcss -i ./resources/main.css -o ./resources/build/main.css --watch
```
then just build it
```
go get
go build
```
### how 2 run
copy the config.example.yml file to config.yml and edit the values accordingly, then just run the binary and crack it open in your web browser.

View File

@ -1,14 +0,0 @@
server:
name: "south london"
homepage: "https://southlondon.cc"
admin:
# webroot: "/admin" # Set this if you're running the admin panel on using a
# custom path instead of a subdomain.
# e.g. southlondon.cc/admin instead of admin.southlondon.cc
auth:
gitea-url: "https://tildegit.org"
authorized-users:
- lp0

View File

@ -1,33 +0,0 @@
package database
import (
"time"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
type User struct {
Username string
Token string
UserID string
LastLogin time.Time
}
var db *gorm.DB
var err error
func Open(dbname string) {
db, err = gorm.Open(sqlite.Open("data/"+dbname), &gorm.Config{})
if err != nil {
panic("couldn't connect to database")
}
}
func Migrate() {
db.AutoMigrate(&User{})
}
func (u *User) SaveUser() {
}

17
go.mod
View File

@ -1,17 +0,0 @@
module tildegit.org/southlondon/admin
go 1.17
require (
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
gorm.io/gorm v1.22.5
)
require github.com/mattn/go-sqlite3 v1.14.11 // indirect
require (
github.com/google/uuid v1.3.0
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.4 // indirect
gorm.io/driver/sqlite v1.2.6
)

29
go.sum
View File

@ -1,29 +0,0 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas=
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsFrzQ=
github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4=
gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsjWY=
gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
gorm.io/gorm v1.22.5 h1:lYREBgc02Be/5lSCTuysZZDb6ffL2qrat6fg9CFbvXU=
gorm.io/gorm v1.22.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=

206
main.go
View File

@ -1,206 +0,0 @@
package main
import (
"errors"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"regexp"
"strings"
"text/template"
"time"
"github.com/google/uuid"
"gopkg.in/yaml.v3"
)
// Config types
// ------------
type ServerConfig struct {
Name string
Homepage string
}
type PanelConfig struct {
Host string
WebRoot string
Port int
LogPath string
}
type AuthConfig struct {
GiteaURL string
ClientID string
ClientSecret string
AuthorizedUsers []string
}
type Config struct {
Server ServerConfig
Panel PanelConfig
Auth AuthConfig
}
var config = new(Config)
var redirecturi string
var requesturl string
func loadConfig() (err error) {
configfile, err := ioutil.ReadFile("config.yml")
if err != nil {
return err
}
err = yaml.Unmarshal(configfile, &config)
// todo: check for bad data !!
var re = regexp.MustCompile(`(((ftp|http|https):\/\/)|(\/)|(..\/))(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?`)
tocheck := [2]string{config.Panel.Host, config.Auth.GiteaURL}
for _, val := range tocheck {
if len(re.FindStringIndex(val)) == 0 {
log.Fatalf(`"%s" is not a valid url.`, val)
}
}
if config.Panel.Port > 65535 {
log.Fatalf("port is too big (max 65535)")
}
// init oauth bits
redirecturi = fmt.Sprintf("%s/login/endpoint", config.Panel.Host)
requesturl = fmt.Sprintf("%s/login/oauth/authorize?client_id=%s&redirect_uri=%s&response_type=code&state=STATE",
strings.Trim(config.Auth.GiteaURL, " "),
strings.Trim(config.Auth.ClientID, " "),
strings.Trim(redirecturi, " "))
return err
}
func openLogFile(logfile string) {
if logfile != "" {
lf, err := os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640)
if err != nil {
log.Fatal("OpenLogfile: os.OpenFile:", err)
}
log.SetOutput(lf)
}
}
func logRequest(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("%s %s %s\n", r.RemoteAddr, r.Method, r.URL)
handler.ServeHTTP(w, r)
})
}
func main() {
err := loadConfig()
if err != nil {
log.Fatalf("couldn't load config: %s", err)
}
openLogFile(config.Panel.LogPath)
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
http.HandleFunc("/login/", loginHandler)
http.Handle("/resources/",
http.StripPrefix("/resources/",
http.FileServer(http.Dir("./resources"))))
http.HandleFunc("/", handler)
fmt.Printf("listening on %v\n", config.Panel.Port)
fmt.Printf("Logging to %v\n", config.Panel.LogPath)
err = http.ListenAndServe(fmt.Sprintf(":%d", config.Panel.Port), logRequest(http.DefaultServeMux))
if err != nil {
log.Fatal(err)
}
}
func exists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
func handler(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
loc := fmt.Sprintf("templates%s.html", path)
// var re = regexp.MustCompile(`\.(svg|jpg|jpeg|png|webp|ico|css|js)$`)
// if re.MatchString(path) {
// http.StripPrefix("/resources/",
// http.FileServer(http.Dir("./resources")))
// return
// }
var tmpl string
anonPath := regexp.MustCompile(`^/(signup|login|hello)$`)
m := anonPath.FindStringSubmatch(path)
if m != nil {
userid, err := r.Cookie("user-id")
if errors.As(err, &http.ErrNoCookie) {
http.Redirect(w, r, "/hello", http.StatusFound)
}
fmt.Print(userid)
}
switch path {
case "/":
tmpl = "templates/home.html"
t, _ := template.ParseFiles(tmpl)
t.Execute(w, config)
default:
exists, err := exists(loc)
if err != nil {
log.Fatal(err)
}
if !exists {
http.NotFound(w, r)
return
}
tmpl = fmt.Sprintf("templates%s.html", path)
t, _ := template.ParseFiles(tmpl)
t.Execute(w, config)
}
}
func loginHandler(w http.ResponseWriter, r *http.Request) {
userid, err := r.Cookie("user-id")
fmt.Print(userid, err)
if errors.As(err, &http.ErrNoCookie) {
useridbody := uuid.New()
expiration := time.Now().Add(365 * 24 * time.Hour)
cookie := http.Cookie{Name: "user-id", Value: useridbody.String(), Expires: expiration}
http.SetCookie(w, &cookie)
// todo: store in db
}
switch strings.TrimRight(r.URL.Path, "/") {
case "/login":
http.Redirect(w, r, requesturl, http.StatusFound)
case "/login/endpoint":
loginEndpoint(w, r)
}
}
func loginEndpoint(w http.ResponseWriter, r *http.Request) {
token := r.FormValue("code")
fmt.Print(token)
}

View File

@ -1,18 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
.login {
@apply flex flex-row justify-center items-center m-auto shadow-md bg-slate-50 p-6 pb-8 rounded px-10 border-t-4 border-t-emerald-700
}
}
@layer components {
.button {
@apply w-full bg-gradient-to-t from-emerald-800 to-emerald-700 text-slate-100 rounded py-2 shadow-sm shadow-emerald-800 hover:opacity-95 font-bold;
}
input {
@apply border-slate-300 border-2 rounded bg-slate-100 w-full my-1 p-1 px-2;
}
}

View File

@ -1,7 +0,0 @@
module.exports = {
content: ["./templates/*.html"],
theme: {
extend: {},
},
plugins: [],
}

View File

@ -1,23 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>{{.Server.Name}} Admin Panel</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' type='text/css' media='screen' href='/resources/build/main.css'>
</head>
<body class="bg-slate-200 flex min-h-screen">
<div class="login">
<form>
<h3 class="font-bold mb-6 text-lg text-center">Log in to {{.Server.Name}} Admin</h3>
<a href="/login" class="button my-10 px-16">
Log In With Gitea
</a>
</form>
</div>
</body>
</html>

View File

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Page Title</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' type='text/css' media='screen' href='main.css'>
</head>
<body>
wowzers
</body>
</html>

View File

@ -1 +0,0 @@
leah you better write some fucking tests this time around