package main import ( "context" "encoding/json" "fmt" "io" "net/http" "net/url" "os" "os/signal" "path" "runtime" "syscall" "time" "gitea.urkob.com/mcr-swiss/gogstea/kit/config" ) type user struct { ID int `json:"id"` Login string `json:"login"` LoginName string `json:"login_name"` SourceID int `json:"source_id"` FullName string `json:"full_name"` Email string `json:"email"` AvatarURL string `json:"avatar_url"` HTMLURL string `json:"html_url"` Language string `json:"language"` IsAdmin bool `json:"is_admin"` LastLogin time.Time `json:"last_login"` Created time.Time `json:"created"` Restricted bool `json:"restricted"` Active bool `json:"active"` ProhibitLogin bool `json:"prohibit_login"` Location string `json:"location"` Website string `json:"website"` Description string `json:"description"` Visibility string `json:"visibility"` FollowersCount int `json:"followers_count"` FollowingCount int `json:"following_count"` StarredReposCount int `json:"starred_repos_count"` Username string `json:"username"` } func main() { ctx, cancel := context.WithCancel(signalContext(context.Background())) defer cancel() cfgFile := os.Getenv("CONFIG_FILE") if cfgFile == "" { // Get root path _, filename, _, _ := runtime.Caller(0) cfgFile = path.Join(path.Dir(filename), "configs", "app.yml") } cfg, err := config.LoadConfig(cfgFile) if err != nil { panic(err) } wd, err := os.Getwd() if err != nil { panic(err) } outputFile, err := os.Create(wd + "/output.txt") if err != nil { panic(err) } defer outputFile.Close() cli := http.DefaultClient parsedURL, err := url.Parse(fmt.Sprintf(cfg.Gitea.URL + "/admin/users")) if err != nil { panic(err) } req, err := http.NewRequestWithContext(ctx, http.MethodGet, parsedURL.String(), http.NoBody) if err != nil { panic(err) } // TODO: see how to pass the admin token if so req.Header.Add("Authorization", "token "+cfg.Gitea.ApiKey) req.Header.Add("Content-Type", "application/json") resp, err := cli.Do(req) if err != nil { panic(err) } if resp.StatusCode != http.StatusOK { bts, _ := io.ReadAll(resp.Body) panic(fmt.Errorf("%d | %s: %w", resp.StatusCode, string(bts), err)) } bts, err := io.ReadAll(resp.Body) if err != nil { panic(err) } var users []user if err := json.Unmarshal(bts, &users); err != nil { panic(err) } for _, u := range users { if u.Username == "mcradmin" { continue } // Delete parsedURL, err := url.Parse(fmt.Sprintf("%s/admin/users/%s", cfg.Gitea.URL, u.Username)) if err != nil { panic(err) } req, err := http.NewRequestWithContext(ctx, http.MethodDelete, parsedURL.String(), http.NoBody) if err != nil { panic(err) } req.Header.Add("Authorization", "token "+cfg.Gitea.ApiKey) req.Header.Add("Content-Type", "application/json") resp, err := cli.Do(req) if err != nil { panic(err) } if resp.StatusCode != http.StatusOK { bts, _ := io.ReadAll(resp.Body) if _, err := outputFile.WriteString(fmt.Sprintf("FAILED %d | %s | %d: %s\n", u.ID, u.Email, resp.StatusCode, string(bts))); err != nil { panic(err) } continue } if _, err := outputFile.WriteString(fmt.Sprintf("DELETED %d | %s\n", u.ID, u.Email)); err != nil { panic(err) } } } func signalContext(ctx context.Context) context.Context { ctx, cancel := context.WithCancel(ctx) sigs := make(chan os.Signal, 1) signal.Notify(sigs, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) go func() { <-sigs signal.Stop(sigs) close(sigs) cancel() }() return ctx }