~gitpocket/gitpocket

8
e0cad84176f3a107a44ea141a76ab87d56afcacf
mainfeed-discovery
gitpocket/forge/rename.go -rw-r--r--2.1 KiB ViewLogBlameView rawPermalink f09bf278b0 feat(pages): serve static sites from user subdomains 21 hours ago
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package forge

import (
	"errors"
	"html/template"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

const renameSchema = `
create table if not exists renames (
	old text primary key,
	user integer not null references users(id) on delete cascade
);
`

func (s *Store) RenameUser(id int64, old, name string) error {
	if err := checkName(name); err != nil {
		return err
	}
	tx, err := s.db.Begin()
	if err != nil {
		return err
	}
	defer tx.Rollback()
	if _, err := tx.Exec(`update users set name = ? where id = ?`, name, id); err != nil {
		if strings.Contains(err.Error(), "UNIQUE") {
			return errors.New("That name is taken")
		}
		return err
	}
	tx.Exec(`delete from renames where old = ?`, name)
	if _, err := tx.Exec(`insert into renames(old, user) values (?, ?) on conflict(old) do update set user = excluded.user`, old, id); err != nil {
		return err
	}
	return tx.Commit()
}

func (s *Store) Renamed(old string) (User, bool) {
	var id int64
	if s.db.QueryRow(`select r.user from renames r where r.old = ? and not exists (select 1 from users where name = r.old)`, old).Scan(&id) != nil {
		return User{}, false
	}
	u, err := s.userByID(id)
	return u, err == nil
}

func (s *Server) rename(w http.ResponseWriter, r *http.Request) {
	u := s.require(w, r)
	if u == nil {
		return
	}
	fail := func(msg string) {
		http.Redirect(w, r, "/settings?error="+template.URLQueryEscaper(msg)+"#username", http.StatusSeeOther)
	}
	name := strings.ToLower(strings.TrimSpace(strings.TrimPrefix(strings.TrimSpace(r.FormValue("name")), "~")))
	if name == u.Name {
		http.Redirect(w, r, "/settings", http.StatusSeeOther)
		return
	}
	if _, ok := s.store.CheckPassword(u.Name, r.FormValue("password")); !ok {
		s.limiter.fail(clientIP(r))
		fail("Password is wrong")
		return
	}
	if err := s.store.RenameUser(u.ID, u.Name, name); err != nil {
		fail(err.Error())
		return
	}
	from, to := filepath.Join(s.root, "repos", u.Name), filepath.Join(s.root, "repos", name)
	os.Remove(to)
	if err := os.Rename(from, to); err != nil && !os.IsNotExist(err) {
		s.store.RenameUser(u.ID, name, u.Name)
		fail("Could not move your repositories")
		return
	}
	http.Redirect(w, r, "/settings", http.StatusSeeOther)
}