forked from tildetown/bbj2
		
	todo
This commit is contained in:
		
							parent
							
								
									38854d5461
								
							
						
					
					
						commit
						77b65feb29
					
				| @ -35,7 +35,7 @@ type iostreams struct { | ||||
| 	Out io.Writer | ||||
| } | ||||
| 
 | ||||
| type Opts struct { | ||||
| type options struct { | ||||
| 	ConfigPath string | ||||
| 	IO         iostreams | ||||
| 	Log        func(string) | ||||
| @ -53,7 +53,7 @@ func main() { | ||||
| 		Err: os.Stderr, | ||||
| 		Out: os.Stdout, | ||||
| 	} | ||||
| 	opts := &Opts{ | ||||
| 	opts := &options{ | ||||
| 		ConfigPath: *configFlag, | ||||
| 		Reset:      *resetFlag, | ||||
| 		IO:         io, | ||||
| @ -75,7 +75,7 @@ func main() { | ||||
| 
 | ||||
| type Teardown func() | ||||
| 
 | ||||
| func setupDB(opts *Opts) (Teardown, error) { | ||||
| func setupDB(opts *options) (Teardown, error) { | ||||
| 	db, err := sql.Open("sqlite3", opts.Config.DBPath) | ||||
| 	fmt.Printf("DBG %#v\n", db) | ||||
| 
 | ||||
| @ -84,7 +84,7 @@ func setupDB(opts *Opts) (Teardown, error) { | ||||
| 	return func() { db.Close() }, err | ||||
| } | ||||
| 
 | ||||
| func _main(opts *Opts) error { | ||||
| func _main(opts *options) error { | ||||
| 	cfg, err := parseConfig(opts.ConfigPath) | ||||
| 	if err != nil { | ||||
| 		fmt.Fprintf(os.Stderr, "could not read config file '%s'", opts.ConfigPath) | ||||
| @ -115,7 +115,7 @@ func _main(opts *Opts) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func ensureSchema(opts Opts) error { | ||||
| func ensureSchema(opts options) error { | ||||
| 	db := opts.DB | ||||
| 
 | ||||
| 	if opts.Reset { | ||||
| @ -150,7 +150,7 @@ func ensureSchema(opts Opts) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func handler(opts Opts, f http.HandlerFunc) http.HandlerFunc { | ||||
| func handler(opts options, f http.HandlerFunc) http.HandlerFunc { | ||||
| 	// TODO make this more real | ||||
| 	return func(w http.ResponseWriter, req *http.Request) { | ||||
| 		opts.Log(req.URL.Path) | ||||
| @ -188,24 +188,56 @@ func writeErrorResponse(w http.ResponseWriter, code int, resp BBJResponse) { | ||||
| 
 | ||||
| // NB breaking: i'm not just returning 200 always but using http status codes | ||||
| 
 | ||||
| func setupAPI(opts Opts) { | ||||
| type AuthInfo struct { | ||||
| 	Username string | ||||
| 	Hash     string | ||||
| } | ||||
| 
 | ||||
| 	http.HandleFunc("/instance_info", handler(opts, func(w http.ResponseWriter, req *http.Request) { | ||||
| func getAuthInfo(opts options, req *http.Request) (ai AuthInfo, err error) { | ||||
| 	ai.Username = req.Header.Get("User") | ||||
| 	ai.Hash = req.Header.Get("Auth") | ||||
| 	if ai.Username == "" { | ||||
| 		err = errors.New("no User header set") | ||||
| 	} | ||||
| 
 | ||||
| 		type instanceInfo struct { | ||||
| 			InstanceName string `json:"instance_name"` | ||||
| 			AllowAnon    bool   `json:"allow_anon"` | ||||
| 			Admins       []string | ||||
| 	if ai.Username == "anon" { | ||||
| 		if !opts.Config.AllowAnon { | ||||
| 			err = errors.New("anonymous access disabled") | ||||
| 		} | ||||
| 		writeResponse(w, BBJResponse{ | ||||
| 			Data: instanceInfo{ | ||||
| 				InstanceName: opts.Config.InstanceName, | ||||
| 				AllowAnon:    opts.Config.AllowAnon, | ||||
| 				Admins:       opts.Config.Admins, | ||||
| 			}, | ||||
| 		}) | ||||
| 	})) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	err = checkAuth(opts, ai) | ||||
| 
 | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func checkAuth(opts options, ai AuthInfo) error { | ||||
| 	db := opts.DB | ||||
| 	stmt, err := db.Prepare("select auth_hash from users where user_name = ?") | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("db error: %w", err) | ||||
| 	} | ||||
| 	defer stmt.Close() | ||||
| 
 | ||||
| 	opts.Logf("querying for %s", ai.Username) | ||||
| 
 | ||||
| 	var authHash string | ||||
| 	if err = stmt.QueryRow(ai.Username).Scan(&authHash); err != nil { | ||||
| 		if strings.Contains(err.Error(), "no rows in result") { | ||||
| 			return errors.New("no such user") | ||||
| 		} | ||||
| 		return fmt.Errorf("db error: %w", err) | ||||
| 	} | ||||
| 
 | ||||
| 	if authHash != ai.Hash { | ||||
| 		return errors.New("bad credentials") | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func setupAPI(opts options) { | ||||
| 	serverErr := func(w http.ResponseWriter, err error) { | ||||
| 		opts.Logf(err.Error()) | ||||
| 		writeErrorResponse(w, 500, BBJResponse{ | ||||
| @ -228,6 +260,21 @@ func setupAPI(opts Opts) { | ||||
| 		}) | ||||
| 	} | ||||
| 
 | ||||
| 	http.HandleFunc("/instance_info", handler(opts, func(w http.ResponseWriter, req *http.Request) { | ||||
| 		type instanceInfo struct { | ||||
| 			InstanceName string `json:"instance_name"` | ||||
| 			AllowAnon    bool   `json:"allow_anon"` | ||||
| 			Admins       []string | ||||
| 		} | ||||
| 		writeResponse(w, BBJResponse{ | ||||
| 			Data: instanceInfo{ | ||||
| 				InstanceName: opts.Config.InstanceName, | ||||
| 				AllowAnon:    opts.Config.AllowAnon, | ||||
| 				Admins:       opts.Config.Admins, | ||||
| 			}, | ||||
| 		}) | ||||
| 	})) | ||||
| 
 | ||||
| 	http.HandleFunc("/user_register", handler(opts, func(w http.ResponseWriter, req *http.Request) { | ||||
| 		if req.Method != "POST" { | ||||
| 			badMethod(w) | ||||
| @ -236,7 +283,7 @@ func setupAPI(opts Opts) { | ||||
| 
 | ||||
| 		type AuthArgs struct { | ||||
| 			Username string `json:"user_name"` | ||||
| 			AuthHash string `json:"auth_hash"` | ||||
| 			Hash     string `json:"auth_hash"` | ||||
| 		} | ||||
| 
 | ||||
| 		var args AuthArgs | ||||
| @ -245,44 +292,34 @@ func setupAPI(opts Opts) { | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		if args.AuthHash == "" || args.Username == "" { | ||||
| 		if args.Hash == "" || args.Username == "" { | ||||
| 			invalidArgs(w) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		db := opts.DB | ||||
| 		stmt, err := db.Prepare("select auth_hash from users where user_name = ?") | ||||
| 		if err != nil { | ||||
| 			serverErr(w, err) | ||||
| 			return | ||||
| 		} | ||||
| 		defer stmt.Close() | ||||
| 
 | ||||
| 		opts.Logf("querying for %s", args.Username) | ||||
| 
 | ||||
| 		var authHash string | ||||
| 		err = stmt.QueryRow(args.Username).Scan(&authHash) | ||||
| 		if err == nil { | ||||
| 		if err := checkAuth(opts, AuthInfo{args.Username, args.Hash}); err == nil { | ||||
| 			opts.Logf("found %s", args.Username) | ||||
| 			// code 4 apparently | ||||
| 			writeErrorResponse(w, 403, BBJResponse{ | ||||
| 				Error: true, | ||||
| 				Data:  "user already exists", | ||||
| 			}) | ||||
| 			return | ||||
| 		} else if err != nil && !strings.Contains(err.Error(), "no rows in result") { | ||||
| 		} else if err.Error() != "no such user" { | ||||
| 			serverErr(w, err) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		stmt, err = db.Prepare(`INSERT INTO users VALUES (?, ?, ?, "", "", 0, 0, ?)`) | ||||
| 		db := opts.DB | ||||
| 		stmt, err := db.Prepare(`INSERT INTO users VALUES (?, ?, ?, "", "", 0, 0, ?)`) | ||||
| 		id, err := uuid.NewRandom() | ||||
| 		if err != nil { | ||||
| 			serverErr(w, err) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		_, err = stmt.Exec(id, args.Username, args.AuthHash, time.Now()) | ||||
| 		_, err = stmt.Exec(id, args.Username, args.Hash, time.Now()) | ||||
| 		if err != nil { | ||||
| 			serverErr(w, err) | ||||
| 		} | ||||
| @ -375,7 +412,29 @@ func setupAPI(opts Opts) { | ||||
| 	})) | ||||
| 
 | ||||
| 	http.HandleFunc("/thread_create", handler(opts, func(w http.ResponseWriter, req *http.Request) { | ||||
| 		if req.Method != "POST" { | ||||
| 			badMethod(w) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		authInfo, err := getAuthInfo(opts, req) | ||||
| 		if err != nil { | ||||
| 			writeErrorResponse(w, 403, BBJResponse{ | ||||
| 				Error: true, | ||||
| 				Data:  err.Error(), | ||||
| 			}) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		fmt.Printf("DBG %#v\n", authInfo) | ||||
| 
 | ||||
| 		type threadCreateArgs struct { | ||||
| 			Title string | ||||
| 			Body  string | ||||
| 		} | ||||
| 
 | ||||
| 		// TODO | ||||
| 
 | ||||
| 		writeResponse(w, BBJResponse{Data: "TODO"}) | ||||
| 	})) | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user