Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ai3
accountserver
Commits
11821eaf
Commit
11821eaf
authored
Jul 01, 2018
by
ale
Browse files
Move resource grouping out of the backend
It makes more sense to have this directly on the User object.
parent
e15acb1e
Changes
5
Hide whitespace changes
Inline
Side-by-side
actions_test.go
View file @
11821eaf
...
...
@@ -249,6 +249,85 @@ func TestService_GetUser(t *testing.T) {
}
}
func
TestService_GetUser_ResourceGroups
(
t
*
testing
.
T
)
{
fb
:=
createFakeBackend
()
tx
,
_
:=
fb
.
NewTransaction
()
svc
,
_
:=
newAccountServiceWithSSO
(
fb
,
testConfig
(),
&
fakeValidator
{})
fb
.
addUser
(
&
User
{
Name
:
"testuser2"
,
Resources
:
[]
*
Resource
{
{
ID
:
NewResourceID
(
ResourceTypeDAV
,
"testuser2"
,
"dav1"
),
Name
:
"dav1"
,
DAV
:
&
WebDAV
{
Homedir
:
"/home/users/investici.org/dav1"
,
},
},
{
ID
:
NewResourceID
(
ResourceTypeDAV
,
"testuser2"
,
"dav1-domain2"
),
Name
:
"dav1-domain2"
,
DAV
:
&
WebDAV
{
Homedir
:
"/home/users/investici.org/dav1/html-domain2.com/subdir"
,
},
},
{
ID
:
NewResourceID
(
ResourceTypeDomain
,
"testuser2"
,
"domain1.com"
),
Name
:
"domain1.com"
,
Website
:
&
Website
{
DocumentRoot
:
"/home/users/investici.org/dav1/html-domain1.com"
,
},
},
{
ID
:
NewResourceID
(
ResourceTypeDomain
,
"testuser2"
,
"domain2.com"
),
Name
:
"domain2.com"
,
Website
:
&
Website
{
DocumentRoot
:
"/home/users/investici.org/dav1/html-domain2.com"
,
},
},
{
ID
:
NewResourceID
(
ResourceTypeDatabase
,
"testuser2"
,
"cn=domain2.com"
,
"db2"
),
ParentID
:
NewResourceID
(
ResourceTypeDomain
,
"testuser2"
,
"domain2.com"
),
Name
:
"db2"
,
Database
:
&
Database
{},
},
},
},
""
,
""
)
req
:=
&
GetUserRequest
{
RequestBase
:
RequestBase
{
Username
:
"testuser2"
,
SSO
:
"testuser2"
,
},
}
user
,
err
:=
svc
.
GetUser
(
context
.
TODO
(),
tx
,
req
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
var
grouped
[]
*
Resource
for
_
,
r
:=
range
user
.
Resources
{
switch
r
.
ID
.
Type
()
{
case
ResourceTypeWebsite
,
ResourceTypeDomain
,
ResourceTypeDAV
,
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
TestService_Auth
(
t
*
testing
.
T
)
{
svc
,
tx
:=
testService
(
"adminuser"
)
...
...
backend/model.go
View file @
11821eaf
...
...
@@ -274,8 +274,6 @@ func (tx *backendTX) GetUser(ctx context.Context, username string) (*accountserv
}
}
groupWebResourcesByHomedir
(
user
.
Resources
)
return
user
,
nil
}
...
...
@@ -538,40 +536,3 @@ func (tx *backendTX) isUIDAvailable(ctx context.Context, uid int) (bool, error)
}
return
true
,
nil
}
var
siteRoot
=
"/home/users/investici.org/"
// The hosting directory for a website is the path component immediately after
// siteRoot. This works also for sites with nested documentRoots.
func
getHostingDir
(
path
string
)
string
{
path
=
strings
.
TrimPrefix
(
path
,
siteRoot
)
if
i
:=
strings
.
Index
(
path
,
"/"
);
i
>
0
{
return
path
[
:
i
]
}
return
path
}
// This is a very specific function meant to address a peculiar characteristic
// of the A/I legacy data model, where DAV accounts and websites do not have an
// explicit relation.
func
groupWebResourcesByHomedir
(
resources
[]
*
accountserver
.
Resource
)
{
// Set the group name to be the 'hostingDir' for sites and DAV
// accounts. Keep a reference of websites by ID so we can later fix the
// group for databases too, via their ParentID.
webs
:=
make
(
map
[
string
]
*
accountserver
.
Resource
)
for
_
,
r
:=
range
resources
{
switch
r
.
ID
.
Type
()
{
case
accountserver
.
ResourceTypeWebsite
,
accountserver
.
ResourceTypeDomain
:
r
.
Group
=
getHostingDir
(
r
.
Website
.
DocumentRoot
)
webs
[
r
.
ID
.
String
()]
=
r
case
accountserver
.
ResourceTypeDAV
:
r
.
Group
=
getHostingDir
(
r
.
DAV
.
Homedir
)
}
}
// Fix databases in a second pass.
for
_
,
r
:=
range
resources
{
if
r
.
ID
.
Type
()
==
accountserver
.
ResourceTypeDatabase
&&
!
r
.
ParentID
.
Empty
()
{
r
.
Group
=
webs
[
r
.
ParentID
.
String
()]
.
Group
}
}
}
backend/model_test.go
View file @
11821eaf
...
...
@@ -102,7 +102,6 @@ func TestModel_GetUser(t *testing.T) {
Name
:
"unodb"
,
Shard
:
"host2"
,
OriginalShard
:
"host2"
,
Group
:
"uno"
,
Status
:
accountserver
.
ResourceStatusActive
,
Database
:
&
accountserver
.
Database
{
CleartextPassword
:
"password"
,
...
...
@@ -126,32 +125,6 @@ func TestModel_GetUser_Has2FA(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
()
...
...
service.go
View file @
11821eaf
...
...
@@ -144,6 +144,9 @@ func (s *authService) validateSSO(ssoToken string) (*sso.Ticket, error) {
return
s
.
validator
.
Validate
(
ssoToken
,
""
,
s
.
ssoService
,
s
.
ssoGroups
)
}
// Fetch a user from the backend and return an error if not found
// (instead of returning a nil User). Also, set dynamic attributes
// like resource Groups.
func
getUserOrDie
(
ctx
context
.
Context
,
tx
TX
,
username
string
)
(
*
User
,
error
)
{
user
,
err
:=
tx
.
GetUser
(
ctx
,
username
)
if
err
!=
nil
{
...
...
@@ -152,6 +155,9 @@ func getUserOrDie(ctx context.Context, tx TX, username string) (*User, error) {
if
user
==
nil
{
return
nil
,
ErrUserNotFound
}
user
.
groupWebResources
()
return
user
,
nil
}
...
...
types.go
View file @
11821eaf
...
...
@@ -352,3 +352,44 @@ type Blog struct {
Name
string
`json:"name"`
URL
string
`json:"url"`
}
const
hardcodedWebRoot
=
"/home/users/investici.org"
// Group web-related resources into groups.
//
// This is a very specific function meant to address a peculiar characteristic
// of the A/I legacy data model, where DAV accounts and websites do not have an
// explicit relation.
//
// TODO: Ideally we should be able to do this without hard-coding the webroot.
func
(
u
*
User
)
groupWebResources
()
{
// Set the group name to be the 'hostingDir' for sites and DAV
// accounts. Keep a reference of websites by ID so we can later fix the
// group for databases too, via their ParentID.
webs
:=
make
(
map
[
string
]
*
Resource
)
for
_
,
r
:=
range
u
.
Resources
{
switch
r
.
ID
.
Type
()
{
case
ResourceTypeWebsite
,
ResourceTypeDomain
:
r
.
Group
=
getHostingDir
(
r
.
Website
.
DocumentRoot
,
hardcodedWebRoot
)
webs
[
r
.
ID
.
String
()]
=
r
case
ResourceTypeDAV
:
r
.
Group
=
getHostingDir
(
r
.
DAV
.
Homedir
,
hardcodedWebRoot
)
}
}
// Fix databases in a second pass.
for
_
,
r
:=
range
u
.
Resources
{
if
r
.
ID
.
Type
()
==
ResourceTypeDatabase
&&
!
r
.
ParentID
.
Empty
()
{
r
.
Group
=
webs
[
r
.
ParentID
.
String
()]
.
Group
}
}
}
// The hosting directory for a website is the path component immediately after
// siteRoot. This works also for sites with nested documentRoots.
func
getHostingDir
(
path
,
siteRoot
string
)
string
{
path
=
strings
.
TrimPrefix
(
strings
.
TrimPrefix
(
path
,
siteRoot
),
"/"
)
if
i
:=
strings
.
Index
(
path
,
"/"
);
i
>
0
{
return
path
[
:
i
]
}
return
path
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment