mirror of https://github.com/tilde-cat/register
154 lines
3.6 KiB
Go
154 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"github.com/tilde-cat/register"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"os/user"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
var (
|
|
verbose = flag.Bool("v", false, "verbose")
|
|
dry = flag.Bool("dry", true, "dry run")
|
|
pending = flag.Bool("pending", false, "list pending registration requests")
|
|
registrationDir = flag.String("reg-dir", "/var/registrations", "directory where registration request will be searched for")
|
|
list = flag.Bool("list", false, "list all pending requests")
|
|
)
|
|
|
|
var idRE = regexp.MustCompile(".*/(.*).json")
|
|
|
|
func idToPath(id string) string {
|
|
return filepath.Join(*registrationDir, id+".json")
|
|
}
|
|
|
|
func pathToId(path string) string {
|
|
m := idRE.FindStringSubmatch(path)
|
|
if len(m) != 2 {
|
|
return ""
|
|
}
|
|
return m[1]
|
|
}
|
|
|
|
func readRequest(id string) (*register.Request, error) {
|
|
return readRequestForm(idToPath(id))
|
|
}
|
|
|
|
func readRequestForm(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 saveRequest(id string, request register.Request) error {
|
|
path := idToPath(id)
|
|
b, err := json.MarshalIndent(request, "", "\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)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
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 getAllPendingRequests() {
|
|
paths, err := filepath.Glob(*registrationDir + "/*.json")
|
|
if err != nil {
|
|
log.Println("falied to list pending requests: %v", err)
|
|
return
|
|
}
|
|
for _, path := range paths {
|
|
r, err := readRequestForm(path)
|
|
if err != nil {
|
|
log.Println(err)
|
|
continue
|
|
}
|
|
if !r.IsPending() {
|
|
continue
|
|
}
|
|
log.Printf("%v: %v", r.Username, pathToId(path))
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
if *list {
|
|
getAllPendingRequests()
|
|
return
|
|
}
|
|
if len(flag.Args()) != 1 {
|
|
fmt.Fprintf(os.Stderr, "usage: %s [OPTIONS] uuid\n", os.Args[0])
|
|
flag.PrintDefaults()
|
|
os.Exit(1)
|
|
}
|
|
id := flag.Arg(0)
|
|
r, err := readRequest(id)
|
|
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"
|
|
if err := saveRequest(id, *r); err != nil {
|
|
log.Fatal("Saving request failed: %v", err)
|
|
}
|
|
}
|