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
6f6114ec
Commit
6f6114ec
authored
Dec 14, 2018
by
ale
Browse files
Add a SearchUser admin method to the API
parent
a3f4990f
Changes
6
Hide whitespace changes
Inline
Side-by-side
actions_test.go
View file @
6f6114ec
...
...
@@ -52,6 +52,16 @@ func (b *fakeBackend) GetUser(_ context.Context, username string) (*RawUser, err
},
nil
}
func
(
b
*
fakeBackend
)
SearchUser
(
_
context
.
Context
,
pattern
string
)
([]
string
,
error
)
{
var
out
[]
string
for
username
:=
range
b
.
users
{
if
strings
.
HasPrefix
(
username
,
pattern
)
{
out
=
append
(
out
,
username
)
}
}
return
out
,
nil
}
func
(
b
*
fakeBackend
)
UpdateUser
(
_
context
.
Context
,
user
*
User
)
error
{
b
.
users
[
user
.
Name
]
=
user
return
nil
...
...
actions_user.go
View file @
6f6114ec
...
...
@@ -7,7 +7,7 @@ import (
umdb
"git.autistici.org/id/usermetadb"
)
// GetUserRequest
is the request type for GetUserAction
.
// GetUserRequest
retrieves a specific User
.
type
GetUserRequest
struct
{
UserRequestBase
...
...
@@ -25,6 +25,37 @@ func (r *GetUserRequest) Serve(rctx *RequestContext) (interface{}, error) {
return
&
rctx
.
User
.
User
,
nil
}
// SearchUserRequest searches the database for users with names
// matching a given pattern. The actual pattern semantics are
// backend-specific (for LDAP, this is a prefix string search).
type
SearchUserRequest
struct
{
AdminRequestBase
Pattern
string
`json:"pattern"`
}
// Validate the request.
func
(
r
*
SearchUserRequest
)
Validate
(
rctx
*
RequestContext
)
error
{
if
r
.
Pattern
==
""
{
return
errors
.
New
(
"empty pattern"
)
}
return
nil
}
// SearchUserResponse is the response type for SearchUserRequest.
type
SearchUserResponse
struct
{
Usernames
[]
string
`json:"usernames"`
}
// Serve the request.
func
(
r
*
SearchUserRequest
)
Serve
(
rctx
*
RequestContext
)
(
interface
{},
error
)
{
usernames
,
err
:=
rctx
.
TX
.
SearchUser
(
rctx
.
Context
,
r
.
Pattern
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
SearchUserResponse
{
Usernames
:
usernames
},
nil
}
// ChangeUserPasswordRequest updates a user's password. It will also take
// care of re-encrypting the user encryption key, if present.
type
ChangeUserPasswordRequest
struct
{
...
...
backend/model.go
View file @
6f6114ec
...
...
@@ -39,6 +39,7 @@ type backend struct {
conn
ldapConn
baseDN
string
userQuery
*
queryTemplate
searchUserQuery
*
queryTemplate
userResourceQueries
[]
*
queryTemplate
resources
*
resourceRegistry
...
...
@@ -88,6 +89,11 @@ func newLDAPBackendWithConn(conn ldapConn, baseDN string) (*backend, error) {
Filter
:
"(objectClass=*)"
,
Scope
:
ldap
.
ScopeBaseObject
,
},
searchUserQuery
:
&
queryTemplate
{
Base
:
joinDN
(
"ou=People"
,
baseDN
),
Filter
:
"(uid=${pattern}*)"
,
Scope
:
ldap
.
ScopeSingleLevel
,
},
userResourceQueries
:
[]
*
queryTemplate
{
// Find all resources that are children of the main uid object.
&
queryTemplate
{
...
...
@@ -263,6 +269,24 @@ func (tx *backendTX) GetUser(ctx context.Context, username string) (*as.RawUser,
return
user
,
nil
}
func
(
tx
*
backendTX
)
SearchUser
(
ctx
context
.
Context
,
pattern
string
)
([]
string
,
error
)
{
// First of all, find the main user object, and just that one.
vars
:=
map
[
string
]
string
{
"pattern"
:
pattern
}
result
,
err
:=
tx
.
search
(
ctx
,
tx
.
backend
.
searchUserQuery
.
query
(
vars
))
if
err
!=
nil
{
return
nil
,
err
}
if
len
(
result
.
Entries
)
==
0
{
return
nil
,
nil
}
var
out
[]
string
for
_
,
entry
:=
range
result
.
Entries
{
out
=
append
(
out
,
entry
.
GetAttributeValue
(
"uid"
))
}
return
out
,
nil
}
func
(
tx
*
backendTX
)
SetUserPassword
(
ctx
context
.
Context
,
user
*
as
.
User
,
encryptedPassword
string
)
(
err
error
)
{
dn
:=
tx
.
getUserDN
(
user
)
tx
.
setAttr
(
dn
,
passwordLDAPAttr
,
encryptedPassword
)
...
...
backend/model_test.go
View file @
6f6114ec
...
...
@@ -163,6 +163,22 @@ func TestModel_GetUser_Resources(t *testing.T) {
}
}
func
TestModel_SearchUser
(
t
*
testing
.
T
)
{
stop
,
b
:=
startServer
(
t
)
defer
stop
()
tx
,
_
:=
b
.
NewTransaction
()
users
,
err
:=
tx
.
SearchUser
(
context
.
Background
(),
"uno"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
len
(
users
)
!=
1
{
t
.
Fatalf
(
"expected 1 user, got %d"
,
len
(
users
))
}
if
users
[
0
]
!=
testUser1
{
t
.
Fatalf
(
"expected %s, got %s"
,
testUser1
,
users
[
0
])
}
}
func
TestModel_SetResourceStatus
(
t
*
testing
.
T
)
{
stop
:=
ldaptest
.
StartServer
(
t
,
&
ldaptest
.
Config
{
Dir
:
"../ldaptest"
,
...
...
server/server.go
View file @
6f6114ec
...
...
@@ -48,6 +48,7 @@ func New(service *as.AccountService, backend as.Backend) *APIServer {
}
s
.
Register
(
"/api/user/get"
,
&
as
.
GetUserRequest
{})
s
.
Register
(
"/api/user/search"
,
&
as
.
SearchUserRequest
{})
s
.
Register
(
"/api/user/create"
,
&
as
.
CreateUserRequest
{})
s
.
Register
(
"/api/user/update"
,
&
as
.
UpdateUserRequest
{})
s
.
Register
(
"/api/user/change_password"
,
&
as
.
ChangeUserPasswordRequest
{})
...
...
service.go
View file @
6f6114ec
...
...
@@ -62,6 +62,10 @@ type TX interface {
SetUserTOTPSecret
(
context
.
Context
,
*
User
,
string
)
error
DeleteUserTOTPSecret
(
context
.
Context
,
*
User
)
error
// Lightweight user search (backend-specific pattern).
// Returns list of matching usernames.
SearchUser
(
context
.
Context
,
string
)
([]
string
,
error
)
// Resource ACL check (does not necessarily hit the database).
CanAccessResource
(
context
.
Context
,
string
,
*
Resource
)
bool
...
...
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