admin.go (view raw)
1package main
2
3// Commands for administering your instance
4// reset user password -> generate link
5// delete user
6
7// Run some scripts to setup your instance
8
9import (
10 "flag"
11 "fmt"
12 "golang.org/x/crypto/ssh/terminal"
13 "io/ioutil"
14 "log"
15 "os"
16 "path"
17 "path/filepath"
18 "syscall"
19)
20
21// TODO improve cli
22func runAdminCommand() {
23 args := flag.Args() // again?
24 if len(args) < 3 {
25 fmt.Println("Expected subcommand with parameter activate-user|delete-user|make-admin|rename-user")
26 os.Exit(1)
27 }
28 var err error
29 switch args[1] {
30 case "activate-user":
31 username := args[2]
32 err = activateUser(username)
33 case "delete-user":
34 username := args[2]
35 // TODO add confirmation
36 err = deleteUser(username)
37 case "make-admin":
38 username := args[2]
39 err = makeAdmin(username)
40 case "rename-user":
41 username := args[2]
42 newUsername := args[3]
43 err = renameUser(username, newUsername)
44 case "set-password":
45 username := args[2]
46 fmt.Print("Enter New Password: ")
47 bytePassword, err := terminal.ReadPassword(int(syscall.Stdin))
48 if err != nil {
49 setPassword(username, bytePassword)
50 }
51 }
52 if err != nil {
53 log.Fatal(err)
54 }
55 // reset password
56
57}
58
59func makeAdmin(username string) error {
60 _, err := DB.Exec("UPDATE user SET admin = true WHERE username = $1", username)
61 if err != nil {
62 return err
63 }
64 log.Println("Made admin user", username)
65 return nil
66}
67
68func setPassword(username string, newPass []byte) error {
69 return nil
70}
71
72func activateUser(username string) error {
73 _, err := DB.Exec("UPDATE user SET active = true WHERE username = ?", username)
74 if err != nil {
75 // TODO verify 1 row updated
76 return err
77 }
78 log.Println("Activated user", username)
79 baseIndex := `# Welcome to Flounder!
80## About
81Welcome to an ultra-lightweight platform for making and sharing small websites. You can get started by editing this page -- remove this content and replace it with whatever you like! It will be live at <your-name>.flounder.online. You can go there right now to see what this page currently looks like. Here is a link to a page which will give you more information about using flounder:
82=> //admin.flounder.online
83
84And here's a guide to the text format that Flounder uses to create pages, Gemini. These pages are converted into HTML so they can be displayed in a web browser.
85=> //admin.flounder.online/gemini_text_guide.gmi
86
87Have fun!`
88 // Redundant filepath.Clean call just in case.
89 username = filepath.Clean(username)
90 os.Mkdir(path.Join(c.FilesDirectory, username), os.ModePerm)
91 ioutil.WriteFile(path.Join(c.FilesDirectory, username, "index.gmi"), []byte(baseIndex), 0644)
92 os.Mkdir(path.Join(c.FilesDirectory, username), os.ModePerm)
93 return nil
94}
95
96func renameUser(oldUsername string, newUsername string) error {
97 err := isOkUsername(newUsername)
98 if err != nil {
99 return err
100 }
101 res, err := DB.Exec("UPDATE user set username = ? WHERE username = ?", newUsername, oldUsername)
102 if err != nil {
103 return err
104 }
105 rowsAffected, err := res.RowsAffected()
106 if rowsAffected != 1 {
107 return fmt.Errorf("No User updated %s %s", oldUsername, newUsername)
108 } else if err != nil {
109 return err
110 }
111 userFolder := path.Join(c.FilesDirectory, oldUsername)
112 newUserFolder := path.Join(c.FilesDirectory, newUsername)
113 err = os.Rename(userFolder, newUserFolder)
114 if err != nil {
115 // This would be bad. User in broken, insecure state.
116 // TODO some sort of better handling?
117 return err
118 }
119 log.Printf("Changed username from %s to %s", oldUsername, newUsername)
120 return nil
121}
122
123func deleteUser(username string) error {
124 _, err := DB.Exec("DELETE FROM user WHERE username = $1", username)
125 if err != nil {
126 return err
127 }
128 username = filepath.Clean(username)
129 err = os.RemoveAll(path.Join(c.FilesDirectory, username))
130 if err != nil {
131 // bad state
132 return err
133 }
134 log.Println("Deleted user", username)
135 return nil
136}