You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
website/auth/ldap.go

149 lines
3.2 KiB
Go

package auth
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
urlpkg "net/url"
"git.phc.dm.unipi.it/phc/website/model"
)
// ldapUser represents an LDAP User, most fields are inherited from [auth.User]
type ldapUser struct {
Uid string `json:"username"`
NumericId int `json:"id"`
Name string `json:"name"`
Surname string `json:"surname"`
Email string `json:"email"`
Role string `json:"role"`
Gecos string `json:"gecos"`
}
// AsUser converts an [ldapUser] to an instance of [auth.User]
func (u ldapUser) AsUser() *model.User {
return &model.User{
Username: u.Uid,
Name: u.Name,
Surname: u.Surname,
Email: u.Email,
FullName: u.Gecos,
}
}
// ldapAuthService just holds the remote host of the HTTP LDAP service to make requests to
type ldapAuthService struct {
Host string
}
func newLDAPAuthService(host string) Service {
return &ldapAuthService{host}
}
// doGetRequest is a utility to make HTTP GET requests
func (a *ldapAuthService) doGetRequest(url string, response interface{}) error {
u, err := urlpkg.JoinPath(a.Host, "poisson-ldap", url)
if err != nil {
return err
}
req, err := http.NewRequest(
"GET", u, bytes.NewBuffer([]byte("")),
)
log.Printf(`%q`, a.Host)
if err != nil {
log.Printf(`GET %q resulted in %v`, url, err)
return err
}
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Printf(`GET %q resulted in %v`, url, err)
return err
}
if err := json.NewDecoder(res.Body).Decode(response); err != nil {
log.Printf(`GET %q resulted in %v`, url, err)
return err
}
return nil
}
// doPostRequest is a utility to make HTTP POST requests
func (a *ldapAuthService) doPostRequest(url string, request interface{}, response interface{}) error {
jsonStr, err := json.Marshal(request)
if err != nil {
return err
}
u, err := urlpkg.JoinPath(a.Host, "ldap", url)
if err != nil {
return err
}
req, err := http.NewRequest("POST", u, bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
return json.NewDecoder(res.Body).Decode(response)
}
func (a *ldapAuthService) GetUser(username string) (*model.User, error) {
var user ldapUser
if err := a.doGetRequest(fmt.Sprintf("/user/%s", username), &user); err != nil {
return nil, err
}
return user.AsUser(), nil
}
func (a *ldapAuthService) GetUsers() ([]*model.User, error) {
ldapUsers := []*ldapUser{}
if err := a.doGetRequest("/users", &ldapUsers); err != nil {
return nil, err
}
users := make([]*model.User, len(ldapUsers))
for i, u := range ldapUsers {
users[i] = u.AsUser()
}
return users, nil
}
func (a *ldapAuthService) GetSession(token string) (*model.Session, error) {
var response model.Session
if err := a.doGetRequest(fmt.Sprintf("/session/%s", token), &response); err != nil {
return nil, err
}
return &response, nil
}
func (a *ldapAuthService) Login(username, password string) (*model.Session, error) {
reqBody := map[string]interface{}{
"username": username,
"password": password,
}
var response model.Session
if err := a.doPostRequest("/login", reqBody, &response); err != nil {
return nil, err
}
return &response, nil
}