blob: aeb6092fc6f74b53d9e46e7249abed1c3328c757 [file] [log] [blame]
// Copyright 2016 The Upspin Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"flag"
"fmt"
"os"
"path/filepath"
"upspin.io/client"
"upspin.io/config"
"upspin.io/errors"
"upspin.io/subcmd"
"upspin.io/upspin"
"upspin.io/user"
)
func (s *State) setupwriters(args ...string) {
const help = `
Setupwriters creates or updates the Writers file for the given domain.
The file lists the names of users granted access to write to the domain's
store server and to create their own root on the directory server.
A wildcard permits access to all users of a domain ("*@example.com").
The user name of the project's directory server is automatically included in
the list, so the directory server can use the store for its own data storage.
`
fs := flag.NewFlagSet("setupwriters", flag.ExitOnError)
where := fs.String("where", filepath.Join(config.Home(), "upspin", "deploy"), "`directory` containing private configuration files")
domain := fs.String("domain", "", "domain `name` for this Upspin installation")
s.ParseFlags(fs, args, help, "setupwriters [-where=$HOME/upspin/deploy] -domain=<domain> <user names>")
if *where == "" {
s.Failf("the -where flag must not be empty")
usageAndExit(fs)
}
if *domain == "" {
s.Failf("the -domain must not be empty")
usageAndExit(fs)
}
var users []upspin.UserName
for _, arg := range fs.Args() {
u, err := user.Clean(upspin.UserName(arg))
if err != nil {
s.Exit(err)
}
users = append(users, u)
}
cfgDir := filepath.Join(subcmd.Tilde(*where), *domain)
if fi, err := os.Stat(cfgDir); err != nil {
s.Exitf("error reading configuration directory: %v", err)
} else if !fi.IsDir() {
s.Exitf("specified location is not a directory: %v", cfgDir)
}
var dirUser upspin.UserName
storeCfg, err := config.FromFile(filepath.Join(cfgDir, "config"))
if errors.Is(errors.NotExist, err) {
storeCfg, err = config.FromFile(filepath.Join(cfgDir, "storeserver", "config"))
if err != nil {
s.Exit(err)
}
dirCfg, err := config.FromFile(filepath.Join(cfgDir, "dirserver", "config"))
if err != nil {
s.Exit(err)
}
// Created by setupdomain -cluster, separate users for dir and store.
dirUser = dirCfg.UserName()
} else if err != nil {
s.Exit(err)
} else {
// Created by setupdomain -cluster=false, one user for dir and store.
dirUser = storeCfg.UserName()
}
storeUser := storeCfg.UserName()
// Act as the store user.
c := client.New(storeCfg)
// Make the store root.
_, err = c.MakeDirectory(upspin.PathName(storeUser) + "/")
if err != nil && !errors.Is(errors.Exist, err) {
s.Exit(err)
}
// Make the Group directory.
_, err = c.MakeDirectory(upspin.PathName(storeUser) + "/Group")
if err != nil && !errors.Is(errors.Exist, err) {
s.Exit(err)
}
// Prepare Access file and put it to the server.
buf := new(bytes.Buffer)
fmt.Fprintf(buf, "*:%v\n", storeUser)
if dirUser != storeUser {
fmt.Fprintf(buf, "l,r:%v\n", dirUser)
}
_, err = c.Put(upspin.PathName(storeUser)+"/Access", buf.Bytes())
if err != nil {
s.Exit(err)
}
// Prepare Writers file and put it to the server.
buf.Reset()
fmt.Fprintln(buf, storeUser)
if dirUser != storeUser {
fmt.Fprintln(buf, dirUser)
}
for _, u := range users {
fmt.Fprintln(buf, u)
}
_, err = c.Put(upspin.PathName(storeUser)+"/Group/Writers", buf.Bytes())
if err != nil {
s.Exit(err)
}
}