This repository has been archived on 2024-01-11. You can view files and clone it, but cannot push or open issues or pull requests.
admin/main.go

207 lines
4.4 KiB
Go
Raw Normal View History

2022-01-26 17:00:22 +00:00
package main
import (
2022-01-29 14:02:37 +00:00
"errors"
2022-01-26 17:00:22 +00:00
"fmt"
2022-01-26 19:28:26 +00:00
"io/ioutil"
"log"
2022-01-26 17:00:22 +00:00
"net/http"
2022-01-27 23:16:13 +00:00
"os"
2022-01-29 14:02:37 +00:00
"regexp"
2022-01-27 23:16:13 +00:00
"strings"
2022-01-27 20:21:09 +00:00
"text/template"
2022-01-29 15:21:16 +00:00
"time"
2022-01-26 19:28:26 +00:00
2022-01-29 15:21:16 +00:00
"github.com/google/uuid"
2022-01-26 19:28:26 +00:00
"gopkg.in/yaml.v3"
2022-01-26 17:00:22 +00:00
)
2022-01-27 20:21:09 +00:00
// Config types
// ------------
2022-01-26 19:28:26 +00:00
type ServerConfig struct {
Name string
Homepage string
}
2022-01-27 23:16:13 +00:00
type PanelConfig struct {
Host string
2022-01-26 19:28:26 +00:00
WebRoot string
2022-01-27 20:21:09 +00:00
Port int
LogPath string
2022-01-26 19:28:26 +00:00
}
type AuthConfig struct {
GiteaURL string
2022-01-27 23:16:13 +00:00
ClientID string
ClientSecret string
2022-01-26 19:28:26 +00:00
AuthorizedUsers []string
}
type Config struct {
Server ServerConfig
2022-01-27 23:16:13 +00:00
Panel PanelConfig
2022-01-26 19:28:26 +00:00
Auth AuthConfig
}
var config = new(Config)
2022-01-27 23:16:13 +00:00
var redirecturi string
var requesturl string
2022-01-26 19:28:26 +00:00
func loadConfig() (err error) {
configfile, err := ioutil.ReadFile("config.yml")
if err != nil {
return err
}
err = yaml.Unmarshal(configfile, &config)
2022-01-27 23:16:13 +00:00
2022-01-29 14:02:15 +00:00
// 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)")
}
2022-01-27 23:16:13 +00:00
// 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, " "))
2022-01-26 19:28:26 +00:00
return err
}
2022-01-27 23:16:13 +00:00
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)
})
}
2022-01-29 14:02:37 +00:00
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)
}
}
2022-01-27 23:16:13 +00:00
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
}
2022-01-27 20:21:09 +00:00
func handler(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
2022-01-29 15:14:09 +00:00
loc := fmt.Sprintf("templates%s.html", path)
2022-01-27 23:16:13 +00:00
// 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
// }
2022-01-29 15:14:09 +00:00
var tmpl string
2022-01-27 23:16:13 +00:00
2022-01-29 15:21:16 +00:00
anonPath := regexp.MustCompile(`^/(signup|login|hello)$`)
m := anonPath.FindStringSubmatch(path)
2022-01-29 15:14:09 +00:00
2022-01-29 15:18:22 +00:00
if m != nil {
2022-01-29 15:14:09 +00:00
userid, err := r.Cookie("user-id")
if errors.As(err, &http.ErrNoCookie) {
http.Redirect(w, r, "/hello", http.StatusFound)
}
fmt.Print(userid)
2022-01-27 23:16:13 +00:00
}
2022-01-29 15:14:09 +00:00
switch path {
case "/":
2022-01-29 15:18:22 +00:00
tmpl = "templates/home.html"
t, _ := template.ParseFiles(tmpl)
t.Execute(w, config)
default:
2022-01-29 15:14:09 +00:00
exists, err := exists(loc)
if err != nil {
log.Fatal(err)
}
2022-01-27 23:16:13 +00:00
2022-01-29 15:14:09 +00:00
if !exists {
http.NotFound(w, r)
return
}
2022-01-29 15:18:22 +00:00
2022-01-29 15:14:09 +00:00
tmpl = fmt.Sprintf("templates%s.html", path)
2022-01-27 23:16:13 +00:00
t, _ := template.ParseFiles(tmpl)
t.Execute(w, config)
}
}
func loginHandler(w http.ResponseWriter, r *http.Request) {
2022-01-29 15:18:22 +00:00
userid, err := r.Cookie("user-id")
fmt.Print(userid, err)
2022-01-29 15:21:16 +00:00
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
}
2022-01-28 00:28:37 +00:00
2022-01-28 00:56:12 +00:00
switch strings.TrimRight(r.URL.Path, "/") {
case "/login":
2022-01-27 23:16:13 +00:00
http.Redirect(w, r, requesturl, http.StatusFound)
2022-01-28 00:56:12 +00:00
case "/login/endpoint":
2022-01-27 23:16:13 +00:00
loginEndpoint(w, r)
2022-01-27 20:21:09 +00:00
}
2022-01-27 23:16:13 +00:00
}
func loginEndpoint(w http.ResponseWriter, r *http.Request) {
token := r.FormValue("code")
fmt.Print(token)
2022-01-27 20:21:09 +00:00
}