Commit e5211476 authored by ale's avatar ale

Remove username from API where we have a Resource

parent 9329ae16
......@@ -39,11 +39,12 @@ type Backend interface {
type TX interface {
Commit(context.Context) error
GetResource(context.Context, ResourceID) (*Resource, error)
UpdateResource(context.Context, *Resource) error
SetResourcePassword(context.Context, *Resource, string) error
GetUser(context.Context, string) (*User, error)
GetResource(context.Context, string, string) (*Resource, error)
UpdateResource(context.Context, string, *Resource) error
SetUserPassword(context.Context, *User, string) error
SetResourcePassword(context.Context, string, *Resource, string) error
GetUserEncryptionKeys(context.Context, *User) ([]*UserEncryptionKey, error)
SetUserEncryptionKeys(context.Context, *User, []*UserEncryptionKey) error
SetUserEncryptionPublicKey(context.Context, *User, []byte) error
......@@ -194,8 +195,8 @@ func (s *AccountService) GetUser(ctx context.Context, tx TX, req *GetUserRequest
// setResourceStatus sets the status of a single resource (shared
// logic between enable / disable resource methods).
func (s *AccountService) setResourceStatus(ctx context.Context, tx TX, username, resourceID, status string) error {
r, err := tx.GetResource(ctx, username, resourceID)
func (s *AccountService) setResourceStatus(ctx context.Context, tx TX, username string, resourceID ResourceID, status string) error {
r, err := tx.GetResource(ctx, resourceID)
if err != nil {
return newBackendError(err)
}
......@@ -203,7 +204,7 @@ func (s *AccountService) setResourceStatus(ctx context.Context, tx TX, username,
return ErrResourceNotFound
}
r.Status = status
if err := tx.UpdateResource(ctx, username, r); err != nil {
if err := tx.UpdateResource(ctx, r); err != nil {
return newBackendError(err)
}
return nil
......@@ -211,7 +212,7 @@ func (s *AccountService) setResourceStatus(ctx context.Context, tx TX, username,
type DisableResourceRequest struct {
RequestBase
ResourceID string `json:"resource_id"`
ResourceID ResourceID `json:"resource_id"`
}
// DisableResource disables a resource belonging to the user.
......@@ -224,7 +225,7 @@ func (s *AccountService) DisableResource(ctx context.Context, tx TX, req *Disabl
type EnableResourceRequest struct {
RequestBase
ResourceID string `json:"resource_id"`
ResourceID ResourceID `json:"resource_id"`
}
// EnableResource enables a resource belonging to the user.
......@@ -275,7 +276,7 @@ func (s *AccountService) ChangeUserPassword(ctx context.Context, tx TX, req *Cha
return newBackendError(err)
}
for _, r := range user.GetResourcesByType(ResourceTypeEmail) {
if err := tx.SetResourcePassword(ctx, user.Name, r, encPass); err != nil {
if err := tx.SetResourcePassword(ctx, r, encPass); err != nil {
return newBackendError(err)
}
}
......@@ -466,8 +467,8 @@ func (s *AccountService) DeleteApplicationSpecificPassword(ctx context.Context,
type ChangeResourcePasswordRequest struct {
RequestBase
ResourceID string `json:"resource_id"`
Password string `json:"password"`
ResourceID ResourceID `json:"resource_id"`
Password string `json:"password"`
}
func (r *ChangeResourcePasswordRequest) Validate() error {
......@@ -490,7 +491,7 @@ func (s *AccountService) ChangeResourcePassword(ctx context.Context, tx TX, req
return newRequestError(err)
}
r, err := tx.GetResource(ctx, req.Username, req.ResourceID)
r, err := tx.GetResource(ctx, req.ResourceID)
if err != nil {
return newBackendError(err)
}
......@@ -499,7 +500,7 @@ func (s *AccountService) ChangeResourcePassword(ctx context.Context, tx TX, req
}
encPass := pwhash.Encrypt(req.Password)
if err := tx.SetResourcePassword(ctx, req.Username, r, encPass); err != nil {
if err := tx.SetResourcePassword(ctx, r, encPass); err != nil {
return newBackendError(err)
}
return nil
......@@ -507,8 +508,8 @@ func (s *AccountService) ChangeResourcePassword(ctx context.Context, tx TX, req
type MoveResourceRequest struct {
RequestBase
ResourceID string `json:"resource_id"`
Shard string `json:"shard"`
ResourceID ResourceID `json:"resource_id"`
Shard string `json:"shard"`
}
type MoveResourceResponse struct {
......@@ -526,7 +527,7 @@ func (s *AccountService) MoveResource(ctx context.Context, tx TX, req *MoveResou
}
// Collect all related resources, as they should all be moved at once.
r, err := tx.GetResource(ctx, req.Username, req.ResourceID)
r, err := tx.GetResource(ctx, req.ResourceID)
if err != nil {
return nil, err
}
......@@ -540,7 +541,7 @@ func (s *AccountService) MoveResource(ctx context.Context, tx TX, req *MoveResou
var resp MoveResourceResponse
for _, r := range resources {
r.Shard = req.Shard
if err := tx.UpdateResource(ctx, req.Username, r); err != nil {
if err := tx.UpdateResource(ctx, r); err != nil {
return nil, err
}
resp.MovedIDs = append(resp.MovedIDs, r.ID.String())
......
......@@ -27,11 +27,11 @@ func (b *fakeBackend) GetUser(_ context.Context, username string) (*User, error)
return b.users[username], nil
}
func (b *fakeBackend) GetResource(_ context.Context, username, resourceID string) (*Resource, error) {
return b.resources[username][resourceID], nil
func (b *fakeBackend) GetResource(_ context.Context, resourceID ResourceID) (*Resource, error) {
return b.resources[resourceID.User()][resourceID.String()], nil
}
func (b *fakeBackend) UpdateResource(_ context.Context, username string, r *Resource) error {
func (b *fakeBackend) UpdateResource(_ context.Context, r *Resource) error {
return nil
}
......@@ -40,7 +40,7 @@ func (b *fakeBackend) SetUserPassword(_ context.Context, user *User, password st
return nil
}
func (b *fakeBackend) SetResourcePassword(_ context.Context, username string, r *Resource, password string) error {
func (b *fakeBackend) SetResourcePassword(_ context.Context, r *Resource, password string) error {
return nil
}
......@@ -84,7 +84,7 @@ type fakeValidator struct {
adminUser string
}
func (v *fakeValidator) Validate(tkt string, nonce string, service string, _ []string) (*sso.Ticket, error) {
func (v *fakeValidator) Validate(tkt, nonce, service string, _ []string) (*sso.Ticket, error) {
// The sso ticket username is just the ticket itself.
var groups []string
if tkt == v.adminUser {
......
......@@ -337,7 +337,7 @@ func (tx *backendTX) DeleteUserTOTPSecret(ctx context.Context, user *accountserv
return nil
}
func (tx *backendTX) SetResourcePassword(ctx context.Context, username string, r *accountserver.Resource, encryptedPassword string) error {
func (tx *backendTX) SetResourcePassword(ctx context.Context, r *accountserver.Resource, encryptedPassword string) error {
dn, _ := tx.backend.resources.GetDN(r.ID)
tx.setAttr(dn, "userPassword", encryptedPassword)
return nil
......@@ -378,12 +378,7 @@ func (tx *backendTX) HasAnyResource(ctx context.Context, resourceIDs []accountse
}
// GetResource returns a ResourceWrapper, as part of a read-modify-update transaction.
func (tx *backendTX) GetResource(ctx context.Context, username, resourceID string) (*accountserver.Resource, error) {
rsrcID, err := accountserver.ParseResourceID(resourceID)
if err != nil {
return nil, err
}
func (tx *backendTX) GetResource(ctx context.Context, rsrcID accountserver.ResourceID) (*accountserver.Resource, error) {
// From the resource ID we can obtain the DN, and fetch it
// straight from LDAP without even doing a real search.
dn, err := tx.backend.resources.GetDN(rsrcID)
......@@ -417,7 +412,7 @@ func (tx *backendTX) GetResource(ctx context.Context, username, resourceID strin
}
// UpdateResource updates a LDAP-backed resource that was obtained by a previous GetResource call.
func (tx *backendTX) UpdateResource(ctx context.Context, username string, r *accountserver.Resource) error {
func (tx *backendTX) UpdateResource(ctx context.Context, r *accountserver.Resource) error {
dn, err := tx.backend.resources.GetDN(r.ID)
if err != nil {
return err
......@@ -464,7 +459,7 @@ func groupWebResourcesByHomedir(resources []*accountserver.Resource) {
webs := make(map[string]*accountserver.Resource)
for _, r := range resources {
switch r.ID.Type() {
case accountserver.ResourceTypeWebsite:
case accountserver.ResourceTypeWebsite, accountserver.ResourceTypeDomain:
r.Group = getHostingDir(r.Website.DocumentRoot)
webs[r.ID.String()] = r
case accountserver.ResourceTypeDAV:
......
......@@ -2,7 +2,6 @@ package backend
import (
"context"
"fmt"
"testing"
"git.autistici.org/ai3/accountserver"
......@@ -15,13 +14,12 @@ const (
testUser1 = "uno@investici.org"
)
func TestModel_GetUser(t *testing.T) {
func startServerAndGetUser(t testing.TB) (func(), accountserver.Backend, *accountserver.User) {
stop := startTestLDAPServer(t, &testLDAPServerConfig{
Port: testLDAPPort,
Base: "dc=example,dc=com",
LDIFs: []string{"testdata/base.ldif", "testdata/test1.ldif"},
})
defer stop()
b, err := NewLDAPBackend(testLDAPAddr, "cn=manager,dc=example,dc=com", "password", "dc=example,dc=com")
if err != nil {
......@@ -37,13 +35,18 @@ func TestModel_GetUser(t *testing.T) {
t.Fatalf("could not find test user %s", testUser1)
}
//t.Logf("%+v", user)
return stop, b, user
}
func TestModel_GetUser(t *testing.T) {
stop, _, user := startServerAndGetUser(t)
defer stop()
if user.Name != testUser1 {
t.Fatalf("bad username: expected %s, got %s", testUser1, user.Name)
}
if len(user.Resources) != 4 {
t.Fatalf("expected 4 resources, got %d", len(user.Resources))
if len(user.Resources) != 5 {
t.Fatalf("expected 5 resources, got %d", len(user.Resources))
}
// Test a specific resource (the database).
......@@ -75,6 +78,59 @@ func TestModel_GetUser(t *testing.T) {
}
}
func TestModel_GetUser_Group(t *testing.T) {
stop, _, user := startServerAndGetUser(t)
defer stop()
var grouped []*accountserver.Resource
for _, r := range user.Resources {
switch r.ID.Type() {
case accountserver.ResourceTypeWebsite, accountserver.ResourceTypeDomain, accountserver.ResourceTypeDAV, accountserver.ResourceTypeDatabase:
grouped = append(grouped, r)
}
}
var group string
for _, r := range grouped {
if r.Group == "" {
t.Errorf("group not set on %s", r.ID)
continue
}
if group == "" {
group = r.Group
} else if group != r.Group {
t.Errorf("wrong group on %s (%s, expected %s)", r.ID, r.Group, group)
}
}
}
func TestModel_GetUser_Resources(t *testing.T) {
stop, b, user := startServerAndGetUser(t)
defer stop()
// Fetch individually all user resources, one by one, and
// check that they match what we have already.
tx2, _ := b.NewTransaction()
for _, r := range user.Resources {
fr, err := tx2.GetResource(context.Background(), r.ID)
if err != nil {
t.Errorf("could not fetch resource %s: %v", r.ID, err)
continue
}
if fr == nil {
t.Errorf("resource %s is missing", r.ID)
continue
}
// It's ok if Group is unset in the GetResource response.
rr := *r
rr.Group = ""
if err := deep.Equal(fr, &rr); err != nil {
t.Errorf("error in fetched resource %s: %v", r.ID, err)
continue
}
}
}
func TestModel_SetResourceStatus(t *testing.T) {
stop := startTestLDAPServer(t, &testLDAPServerConfig{
Port: testLDAPPort,
......@@ -89,8 +145,8 @@ func TestModel_SetResourceStatus(t *testing.T) {
}
tx, _ := b.NewTransaction()
rsrcID := fmt.Sprintf("email/%s/%s", testUser1, testUser1)
r, err := tx.GetResource(context.Background(), testUser1, rsrcID)
rsrcID := accountserver.NewResourceID(accountserver.ResourceTypeEmail, testUser1, testUser1)
r, err := tx.GetResource(context.Background(), rsrcID)
if err != nil {
t.Fatal("GetResource", err)
}
......@@ -98,10 +154,8 @@ func TestModel_SetResourceStatus(t *testing.T) {
t.Fatalf("could not find test resource %s", rsrcID)
}
//t.Logf("%+v", r)
r.Status = accountserver.ResourceStatusInactive
if err := tx.UpdateResource(context.Background(), "uno@investici.org", r); err != nil {
if err := tx.UpdateResource(context.Background(), r); err != nil {
t.Fatal("UpdateResource", err)
}
if err := tx.Commit(context.Background()); err != nil {
......
......@@ -368,7 +368,7 @@ func (h *webdavResourceHandler) GetDN(id accountserver.ResourceID) (string, erro
return "", errors.New("unqualified resource id")
}
dn := replaceVars("cn=${resource},uid=${user},ou=People", map[string]string{
dn := replaceVars("ftpname=${resource},uid=${user},ou=People", map[string]string{
"user": id.User(),
"resource": id.Name(),
})
......@@ -425,7 +425,7 @@ type databaseResourceHandler struct {
baseDN string
}
func makeDatabaseResourceID(dn string) (rsrcID accountserver.ResourceID, parentID accountserver.ResourceID, err error) {
func makeDatabaseResourceID(dn string) (rsrcID, parentID accountserver.ResourceID, err error) {
parsed, perr := ldap.ParseDN(dn)
if perr != nil {
err = perr
......
......@@ -82,6 +82,18 @@ creationDate: 01-08-2013
originalHost: host2
statsId: 2191
dn: cn=example.com,uid=uno@investici.org,ou=People,dc=example,dc=com
status: active
acceptMail: true
objectClass: top
objectClass: virtualHost
cn: example.com
host: host2
documentRoot: /home/users/investici.org/uno/html-example.com
creationDate: 02-08-2013
originalHost: host2
statsId: 2192
dn: dbname=unodb,alias=uno,uid=uno@investici.org,ou=People,dc=example,dc=com
status: active
clearPassword: password
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment