mirror of https://github.com/tilde-cat/register
Added tool for user creation.
This commit is contained in:
parent
318fdb7982
commit
88262eff40
125
main.go
125
main.go
|
@ -1,35 +1,4 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
|
||||
"github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
FormUrl = "/"
|
||||
FormPostUrl = "/post"
|
||||
RequestStatusUrlPrefix = "/status/"
|
||||
ErrorUrl = "/error"
|
||||
)
|
||||
|
||||
var config = struct {
|
||||
Title string
|
||||
}{
|
||||
Title: "~🐱 Sign up!",
|
||||
}
|
||||
|
||||
var statusRE = regexp.MustCompile("^" + RequestStatusUrlPrefix + `(.+)$`)
|
||||
|
||||
type Id uuid.UUID
|
||||
|
||||
func (id Id) String() string {
|
||||
return uuid.UUID(id).String()
|
||||
}
|
||||
package register
|
||||
|
||||
type Request struct {
|
||||
Username string
|
||||
|
@ -46,95 +15,3 @@ func (r *Request) IsValid() bool {
|
|||
r.SSHPublicKey != ""
|
||||
}
|
||||
|
||||
type Io interface {
|
||||
Save(r Request) (Id, error)
|
||||
Load(id Id) (*Request, error)
|
||||
}
|
||||
|
||||
type FsIo struct {
|
||||
}
|
||||
|
||||
func (io *FsIo) Save(r Request) (Id, error) {
|
||||
b, err := json.MarshalIndent(r, "", "\t")
|
||||
if err != nil {
|
||||
return Id{}, err
|
||||
}
|
||||
id := Id(uuid.NewV4())
|
||||
return id, ioutil.WriteFile(id.String()+".json", b, 0600)
|
||||
}
|
||||
|
||||
func (io *FsIo) Load(id Id) (*Request, error) {
|
||||
b, err := ioutil.ReadFile(id.String() + ".json")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var req Request
|
||||
if err := json.Unmarshal(b, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &req, nil
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
Io Io
|
||||
}
|
||||
|
||||
func (s *Server) RequestPage(w http.ResponseWriter, r *http.Request) {
|
||||
m := statusRE.FindStringSubmatch(r.URL.String())
|
||||
if len(m) != 2 {
|
||||
http.Error(w, "missing request id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
uid := m[1]
|
||||
id, err := uuid.FromString(uid)
|
||||
if err != nil {
|
||||
http.Error(w, "no such request: '"+uid+"'", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
req, err := s.Io.Load(Id(id))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
config := map[string]interface{}{
|
||||
"Global": config,
|
||||
"Status": req.Status,
|
||||
}
|
||||
statusTemplate.ExecuteTemplate(w, "status", config)
|
||||
}
|
||||
|
||||
func (s *Server) FormPostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm()
|
||||
req := Request{}
|
||||
req.Username = r.PostFormValue("username")
|
||||
req.Email = r.PostFormValue("email")
|
||||
req.Why = r.PostFormValue("why")
|
||||
req.SSHPublicKey = r.PostFormValue("sshpublickey")
|
||||
req.Status = "Pending"
|
||||
if !req.IsValid() {
|
||||
log.Println("Invalid request", r.PostForm)
|
||||
http.Redirect(w, r, ErrorUrl, http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
id, err := s.Io.Save(req)
|
||||
log.Println("Valid request", r.PostForm, err)
|
||||
http.Redirect(w, r, RequestStatusUrlPrefix+id.String(), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (s *Server) FormPage(w http.ResponseWriter, r *http.Request) {
|
||||
formTemplate.Execute(w, config)
|
||||
}
|
||||
|
||||
func (s *Server) ErrorPage(w http.ResponseWriter, r *http.Request) {
|
||||
errorTemplate.Execute(w, config)
|
||||
}
|
||||
|
||||
func main() {
|
||||
var io FsIo
|
||||
server := Server{Io: &io}
|
||||
http.HandleFunc(RequestStatusUrlPrefix, server.RequestPage)
|
||||
http.HandleFunc(FormPostUrl, server.FormPostHandler)
|
||||
http.HandleFunc(FormUrl, server.FormPage)
|
||||
http.HandleFunc(ErrorUrl, server.ErrorPage)
|
||||
log.Fatal(http.ListenAndServe("localhost:5678", nil))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
|
||||
"github.com/tilde-cat/register"
|
||||
"github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
FormUrl = "/"
|
||||
FormPostUrl = "/post"
|
||||
RequestStatusUrlPrefix = "/status/"
|
||||
ErrorUrl = "/error"
|
||||
)
|
||||
|
||||
var config = struct {
|
||||
Title string
|
||||
}{
|
||||
Title: "~🐱 Sign up!",
|
||||
}
|
||||
|
||||
var statusRE = regexp.MustCompile("^" + RequestStatusUrlPrefix + `(.+)$`)
|
||||
|
||||
type Id uuid.UUID
|
||||
|
||||
func (id Id) String() string {
|
||||
return uuid.UUID(id).String()
|
||||
}
|
||||
|
||||
type Io interface {
|
||||
Save(r register.Request) (Id, error)
|
||||
Load(id Id) (*register.Request, error)
|
||||
}
|
||||
|
||||
type FsIo struct {
|
||||
}
|
||||
|
||||
func (io *FsIo) Save(r register.Request) (Id, error) {
|
||||
b, err := json.MarshalIndent(r, "", "\t")
|
||||
if err != nil {
|
||||
return Id{}, err
|
||||
}
|
||||
id := Id(uuid.NewV4())
|
||||
return id, ioutil.WriteFile(id.String()+".json", b, 0600)
|
||||
}
|
||||
|
||||
func (io *FsIo) Load(id Id) (*register.Request, error) {
|
||||
b, err := ioutil.ReadFile(id.String() + ".json")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var req register.Request
|
||||
if err := json.Unmarshal(b, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &req, nil
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
Io Io
|
||||
}
|
||||
|
||||
func (s *Server) RequestPage(w http.ResponseWriter, r *http.Request) {
|
||||
m := statusRE.FindStringSubmatch(r.URL.String())
|
||||
if len(m) != 2 {
|
||||
http.Error(w, "missing request id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
uid := m[1]
|
||||
id, err := uuid.FromString(uid)
|
||||
if err != nil {
|
||||
http.Error(w, "no such request: '"+uid+"'", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
req, err := s.Io.Load(Id(id))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
config := map[string]interface{}{
|
||||
"Global": config,
|
||||
"Status": req.Status,
|
||||
}
|
||||
statusTemplate.ExecuteTemplate(w, "status", config)
|
||||
}
|
||||
|
||||
func (s *Server) FormPostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm()
|
||||
req := register.Request{}
|
||||
req.Username = r.PostFormValue("username")
|
||||
req.Email = r.PostFormValue("email")
|
||||
req.Why = r.PostFormValue("why")
|
||||
req.SSHPublicKey = r.PostFormValue("sshpublickey")
|
||||
req.Status = "Pending"
|
||||
if !req.IsValid() {
|
||||
log.Println("Invalid request", r.PostForm)
|
||||
http.Redirect(w, r, ErrorUrl, http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
id, err := s.Io.Save(req)
|
||||
log.Println("Valid request", r.PostForm, err)
|
||||
http.Redirect(w, r, RequestStatusUrlPrefix+id.String(), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (s *Server) FormPage(w http.ResponseWriter, r *http.Request) {
|
||||
formTemplate.Execute(w, config)
|
||||
}
|
||||
|
||||
func (s *Server) ErrorPage(w http.ResponseWriter, r *http.Request) {
|
||||
errorTemplate.Execute(w, config)
|
||||
}
|
||||
|
||||
func main() {
|
||||
var io FsIo
|
||||
server := Server{Io: &io}
|
||||
http.HandleFunc(RequestStatusUrlPrefix, server.RequestPage)
|
||||
http.HandleFunc(FormPostUrl, server.FormPostHandler)
|
||||
http.HandleFunc(FormUrl, server.FormPage)
|
||||
http.HandleFunc(ErrorUrl, server.ErrorPage)
|
||||
log.Fatal(http.ListenAndServe("localhost:5678", nil))
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"flag"
|
||||
"bytes"
|
||||
"strconv"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"os/exec"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/tilde-cat/register"
|
||||
)
|
||||
|
||||
var verbose = flag.Bool("v", false, "verbose")
|
||||
var dry = flag.Bool("dry", true, "dry run")
|
||||
|
||||
func readRequest(path string) (*register.Request, error) {
|
||||
b, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var r register.Request
|
||||
err = json.Unmarshal(b, &r)
|
||||
return &r, err
|
||||
}
|
||||
|
||||
func shell(cmd string, args... string) {
|
||||
var errOut bytes.Buffer
|
||||
c := exec.Command(cmd, args...)
|
||||
c.Stderr = &errOut
|
||||
if err := c.Run(); err != nil {
|
||||
log.Fatalf("%v failed:\n%v", cmd, errOut.String())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func fixKey(key string) string {
|
||||
return strings.Replace(strings.Replace(key, "\n", "", -1), "\r", "", -1)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if len(flag.Args()) != 1 {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s [OPTIONS] file\n", os.Args[0])
|
||||
flag.PrintDefaults()
|
||||
os.Exit(1)
|
||||
}
|
||||
path := flag.Arg(0)
|
||||
r, err := readRequest(path)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to read request: %v", err)
|
||||
}
|
||||
if *verbose || *dry {
|
||||
log.Printf("Username: '%v'\n", r.Username)
|
||||
log.Printf("Email: '%v'\n", r.Email)
|
||||
log.Printf("Why:\n%v\n", r.Why)
|
||||
log.Printf("SSH key:\n%v\n", r.SSHPublicKey)
|
||||
log.Printf("Status: '%v'\n", r.Status)
|
||||
}
|
||||
if r.Status != "Pending" {
|
||||
log.Fatalf("This request is not pending")
|
||||
}
|
||||
if *dry {
|
||||
log.Println("dry run ends")
|
||||
return
|
||||
}
|
||||
|
||||
shell("adduser", "--disabled-login", "--gecos", "", r.Username)
|
||||
authorizedKeysPath := "/home/"+r.Username+"/.ssh/authorized_keys"
|
||||
if err = ioutil.WriteFile(authorizedKeysPath, []byte(fixKey(r.SSHPublicKey)), 0664); err != nil {
|
||||
log.Fatal("sshkey instalation failed: %v", err)
|
||||
}
|
||||
user, err := user.Lookup(r.Username)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get user '%v': %v", r.Username, err)
|
||||
}
|
||||
if *verbose {
|
||||
log.Printf("user: %#v\n", user)
|
||||
}
|
||||
userId, _ := strconv.Atoi(user.Uid)
|
||||
groupId, _ := strconv.Atoi(user.Gid)
|
||||
if err := os.Chown(authorizedKeysPath, userId, groupId); err != nil {
|
||||
log.Fatal("chown failed: %v", err)
|
||||
}
|
||||
r.Status = "Account created"
|
||||
b, err := json.MarshalIndent(r, "", "\t")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to serialize request: %v\n", err)
|
||||
}
|
||||
if err := ioutil.WriteFile(path, b, 0666); err != nil {
|
||||
log.Fatalf("Failed to save request: %v\n", err)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue