Code organization and how to add functionality===The codebase is still fairly messy: we just haven't found (yet?) agood way to abstract functions and interfaces that minimizes theeffort of writing business logic.Anyway, in case you want to add new functionality to theaccountserver, here's a quick overview of what to do and what toconsider:## Adding functionality to the backendThe backend interface is in [service.go](service.go)(the*Backend*and *TX* interfaces), and has methods to manipulate objects in theuser database. The data types used by this interface (most importantly*User* and *Resource*) are defined in [types.go](types.go) instead.In some cases, your new functionality may require changes in the datamodel as well. There are two major options available, depending on thedesired visibility of the new data:### Adding public dataIn this case you need to add *publicly-visible* data to the User or toa Resource. This is relatively straightforward as it requires nochanges to the TX interface.Suppose you are adding a field called *color* (whatever, doesn'tmatter) to email resources.* Add the *color* field to the *Email* type in types.go:```type Email struct { ... Color string `json:"color"`}```* The LDAP backend implementation needs to know which LDAP attribute this field corresponds to. This is done in [backend/resources.go](backend/resources.go), in the FromLDAP/ToLDAP methods of the *emailResourceHandler* type:```func (h *emailResourceHandler) FromLDAP(entry *ldap.Entry) (*accountserver.Resource, error) { ... return &accountserver.Resource{ ... Email: &accountserver.Email{ ... Color: entry.GetAttributeValue("color"), }, }}func (h *emailResourceHandler) ToLDAP(rsrc *accountserver.Resource) []ldap.PartialAttribute { return []ldap.PartialAttribute{ ... {Type: "color", Vals: s2l(rsrc.Email.Color)}, }}```* Validation code for the new field must be added to [validators.go](validators.go) in the validationContext.validEmailResource function:```func (v *validationContext) validEmailResource() ResourceValidatorFunc { return func(ctx context.Context, r *Resource, user *User) error { ... if r.Email.Color != "blue" { return errors.New("oh no, the color is wrong") } ... }}```* If a newly created email resource should have a default value for the *color* field, it needs to be added to the templateContext.emailResourceTemplate function in the same validators.go file:```func (c *templateContext) emailResourceTemplate(ctx context.Context, r *Resource, user *User) { ... r.Email.Color = "blue" ...}```### Adding private dataWhen adding new private data, more complex changes are required: privatedata should not be stored in the public data types, but one should usededicated methods on the TX interface instead.Suppose for instance you want to add a new authentication mechanism,*third-factor authentication* or *3FA*. The authentication handler(which is not part of accountserver!) requires a secret *magic word*to authenticate a user, so we need a dedicated TX method to set it. Wewould also like to be able to tell whether a user has 3FA enabled ornot (it's nice to show it in the user management panel, for instance),so we are going to add a boolean *Has3FA* field to the *User* typetoo.This might result in something like:```type TX interface { ... SetUser3FAMagicWord(context.Context, *User, string) error}```which would then need to be implemented by the LDAP backend.## Adding functionality to the APIOnce the backend changes, where necessary, have been made, you maywant to add a public method to the API, to allow clients to manipulatethe new data. The public API is defined by the *AccountService*type. This type is defined in [service.go](service.go), which containsbasic private functionality, but all "business logic" methods areactually in [actions.go](actions.go). The API is then exported as anHTTP service by [server/server.go](server/server.go).As an example, let's add a new *SetEmailColor* API method to set the*color* attribute of email resources from an earlier exampleabove. We're going to need a request type, but the action returns nodata so we can avoid defining a response type.There's a bit of boilerplate involved. In brief, this is going to be a*resource*-level method (since it operates on a specific resource, noton the user itself), and we're going to allow users to set their own"email color".So, in actions.go:```type SetEmailColorRequest struct { ResourceRequestBase Color string `json:"color"`}func (s *AccountService) SetEmailColor(ctx context.Context, tx TX, req *SetEmailColorRequest) error { return s.handleResourceRequest(ctx, tx, req, s.authResource(req.ResourceRequestBase), func(ctx context.Context, r *Resource) error { r.Email.Color = req.Color return tx.UpdateResource(ctx, r) })}```In reality we will want to do more things, like validating the *color*field in the incoming request.Finally, the new API method must be exposed on the HTTP service. Inserver/server.go we should create a new handler wrapper function:```func (s *AccountServer) handleSetEmailColor(tx as.TX, w http.ResponseWriter, r *http.Request) (interface{}, error) { var req as.SetEmailColorRequest return handleJSON(w, r, &req, func(ctx context.Context) (interface{}, error) { return s.service.SetEmailColor(ctx, tx, &req) })}func (s *AccountServer) Handler() http.Handler { ... h.HandleFunc("/api/resource/email/set_color", s.withTx(s.handleSetEmailColor))}```