@@ 39,7 39,6 @@ import (
"golang.org/x/image/draw"
"golang.org/x/net/idna"
"netlandish.com/x/gobwebs"
- auditlog "netlandish.com/x/gobwebs-auditlog"
oauth2 "netlandish.com/x/gobwebs-oauth2"
gaccounts "netlandish.com/x/gobwebs/accounts"
gcore "netlandish.com/x/gobwebs/core"
@@ 89,6 88,7 @@ func (r *mutationResolver) AddOrganization(ctx context.Context, input model.Orga
return nil, valid.ErrAuthorization
}
user := tokenUser.User.(*models.User)
+ c := server.EchoForContext(ctx)
lang := links.GetLangFromRequest(server.EchoForContext(ctx).Request(), user)
lt := localizer.GetLocalizer(lang)
@@ 182,6 182,20 @@ func (r *mutationResolver) AddOrganization(ctx context.Context, input model.Orga
return nil, err
}
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_ORG_ADDED,
+ fmt.Sprintf("Added organization '%s' (%d)", org.Slug, org.ID),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
return org, nil
}
@@ 352,6 366,21 @@ func (r *mutationResolver) AddLink(ctx context.Context, input *model.LinkInput)
}
}
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ err = models.RecordAuditLog(
+ ctx,
+ userID,
+ c.RealIP(),
+ models.LOG_BOOKMARK_ADDED,
+ fmt.Sprintf("Added bookmark '%s'", OrgLink.Hash),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
return OrgLink, nil
}
@@ 545,6 574,28 @@ func (r *mutationResolver) UpdateLink(ctx context.Context, input *model.UpdateLi
return nil, err
}
}
+
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ ltype := models.LOG_BOOKMARK_UPDATED
+ ldet := "bookmark"
+ if orgLink.Type == models.NoteType {
+ ltype = models.LOG_NOTE_UPDATED
+ ldet = "note"
+ }
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ ltype,
+ fmt.Sprintf("Updated %s '%s'", ldet, orgLink.Hash),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
return orgLink, nil
}
@@ 580,28 631,28 @@ func (r *mutationResolver) DeleteLink(ctx context.Context, hash string) (*model.
}
link := orgLinks[0]
- // If the user is not the link creator, verify org write permissions
- if link.UserID != int(user.ID) {
- opts = &database.FilterOptions{
- Filter: sq.And{
- sq.Expr("o.id = ?", link.OrgID),
- sq.Expr("o.is_active = true"),
- },
- Limit: 1,
- }
+ opts = &database.FilterOptions{
+ Filter: sq.And{
+ sq.Expr("o.id = ?", link.OrgID),
+ sq.Expr("o.is_active = true"),
+ },
+ Limit: 1,
+ }
- orgs, err := models.GetOrganizations(ctx, opts)
- if err != nil {
- return nil, err
- }
+ orgs, err := models.GetOrganizations(ctx, opts)
+ if err != nil {
+ return nil, err
+ }
- if len(orgs) == 0 {
- validator.Error("%s", lt.Translate("This user is not allowed to perform this action")).
- WithCode(valid.ErrNotFoundCode)
- return nil, nil
- }
+ if len(orgs) == 0 {
+ validator.Error("%s", lt.Translate("This user is not allowed to perform this action")).
+ WithCode(valid.ErrNotFoundCode)
+ return nil, nil
+ }
+ org := orgs[0]
- org := orgs[0]
+ // If the user is not the link creator, verify org write permissions
+ if link.UserID != int(user.ID) {
if !org.CanWrite(ctx, user) {
validator.Error("%s", lt.Translate("This user is not allowed to perform this action")).
WithCode(valid.ErrNotFoundCode)
@@ 628,6 679,28 @@ func (r *mutationResolver) DeleteLink(ctx context.Context, hash string) (*model.
return nil, err
}
}
+
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ ltype := models.LOG_BOOKMARK_DELETED
+ ldet := "bookmark"
+ if link.Type == models.NoteType {
+ ltype = models.LOG_NOTE_DELETED
+ ldet = "note"
+ }
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ ltype,
+ fmt.Sprintf("Deleted %s '%s'", ldet, link.Hash),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
deletePayload.Success = true
deletePayload.ObjectID = deletedID
return deletePayload, nil
@@ 929,6 1002,22 @@ func (r *mutationResolver) AddMember(ctx context.Context, input *model.MemberInp
if err != nil {
return nil, err
}
+
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ mdata["user_id"] = user.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(currentUser.ID),
+ c.RealIP(),
+ models.LOG_MEMBER_ADDED,
+ fmt.Sprintf("Added member %s", user.Email),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
addMemberPayload.Success = true
return addMemberPayload, nil
}
@@ 977,8 1066,9 @@ func (r *mutationResolver) DeleteMember(ctx context.Context, orgSlug string, ema
return nil, nil
}
+ email = strings.ToLower(email)
opts := &database.FilterOptions{
- Filter: sq.Eq{"u.email": strings.ToLower(email)},
+ Filter: sq.Eq{"u.email": email},
Limit: 1,
}
@@ 1015,6 1105,22 @@ func (r *mutationResolver) DeleteMember(ctx context.Context, orgSlug string, ema
return nil, err
}
}
+
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ mdata["user_id"] = duser.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_MEMBER_REMOVED,
+ fmt.Sprintf("Removed member %s", email),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
addMemberPayload.Success = true
addMemberPayload.Message = lt.Translate("The member was removed successfully")
}
@@ 1126,6 1232,22 @@ func (r *mutationResolver) ConfirmMember(ctx context.Context, key string) (*mode
if err != nil {
return nil, err
}
+
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_MEMBER_CONFIRMED,
+ fmt.Sprintf("Confirmed member %s", user.Email),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
addMemberPayload := &model.AddMemberPayload{
Success: true,
Message: lt.Translate("The user was added successfully"),
@@ 1585,6 1707,21 @@ func (r *mutationResolver) UpdateProfile(ctx context.Context, input *model.Profi
}
}
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = personalOrg.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_PROFILE_UPDATED,
+ fmt.Sprintf("Updated profile"),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
return user, nil
}
@@ 1764,6 1901,21 @@ func (r *mutationResolver) UpdateOrganization(ctx context.Context, input *model.
return nil, err
}
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_ORG_UPDATED,
+ fmt.Sprintf("Updated organization '%s' (%d)", org.Slug, org.ID),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
return org, nil
}
@@ 1901,6 2053,23 @@ func (r *mutationResolver) AddDomain(ctx context.Context, input model.DomainInpu
return nil, err
}
}
+
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ mdata["domain_id"] = domain.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_DOMAIN_ADDED,
+ fmt.Sprintf("Added domain '%s'", domain.LookupName),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
return domain, nil
}
@@ 1969,6 2138,22 @@ func (r *mutationResolver) DeleteDomain(ctx context.Context, id int) (*model.Del
return nil, err
}
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = domain.OrgID
+ mdata["domain_id"] = domain.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_DOMAIN_DELETED,
+ fmt.Sprintf("Deleted domain '%s'", domain.LookupName),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
deletePayload.Success = true
deletePayload.ObjectID = fmt.Sprint(id)
return deletePayload, nil
@@ 2170,14 2355,16 @@ func (r *mutationResolver) AddLinkShort(ctx context.Context, input *model.LinkSh
}
}
- alog := auditlog.New(
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ err = models.RecordAuditLog(
+ ctx,
int(user.ID),
c.RealIP(),
models.LOG_SHORT_ADDED,
- fmt.Sprintf("Added short link '%s'", linkShort.ShortCode),
+ fmt.Sprintf("Added short link '%s' (%d)", linkShort.ShortCode, linkShort.ID),
+ mdata,
)
- alog.AddMetadata("org_id", org.ID)
- err = alog.Store(ctx)
if err != nil {
return nil, err
}
@@ 2192,6 2379,7 @@ func (r *mutationResolver) UpdateLinkShort(ctx context.Context, input *model.Upd
return nil, valid.ErrAuthorization
}
user := tokenUser.User.(*models.User)
+ c := server.EchoForContext(ctx)
lang := links.GetLangFromRequest(server.EchoForContext(ctx).Request(), user)
lt := localizer.GetLocalizer(lang)
@@ 2362,6 2550,20 @@ func (r *mutationResolver) UpdateLinkShort(ctx context.Context, input *model.Upd
}
}
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_SHORT_UPDATED,
+ fmt.Sprintf("Updated short link '%s' (%d)", linkShort.ShortCode, linkShort.ID),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
return linkShort, nil
}
@@ 2372,6 2574,7 @@ func (r *mutationResolver) DeleteLinkShort(ctx context.Context, id int) (*model.
return nil, valid.ErrAuthorization
}
user := tokenUser.User.(*models.User)
+ c := server.EchoForContext(ctx)
lang := links.GetLangFromRequest(server.EchoForContext(ctx).Request(), user)
lt := localizer.GetLocalizer(lang)
deletePayload := &model.DeletePayload{
@@ 2413,6 2616,21 @@ func (r *mutationResolver) DeleteLinkShort(ctx context.Context, id int) (*model.
if err != nil {
return nil, err
}
+
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_SHORT_DELETED,
+ fmt.Sprintf("Deleted short link '%s' (%d)", link.ShortCode, link.ID),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
deletePayload.Success = true
deletePayload.ObjectID = deletedID
return deletePayload, nil
@@ 2714,6 2932,22 @@ func (r *mutationResolver) AddListing(ctx context.Context, input *model.AddListi
}
}
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ mdata["list_id"] = listing.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_LIST_ADDED,
+ fmt.Sprintf("Added link listing '%s' (%d)", listing.Slug, listing.ID),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
return listing, nil
}
@@ 2799,6 3033,24 @@ func (r *mutationResolver) AddListingLink(ctx context.Context, input *model.AddL
if err != nil {
return nil, err
}
+
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ mdata["list_id"] = listing.ID
+ mdata["list_link_id"] = listingLink.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_LIST_LINK_ADDED,
+ fmt.Sprintf("Added listing entry '%s' (%d)", listingLink.Title, listingLink.ID),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
return listingLink, nil
}
@@ 3126,6 3378,23 @@ func (r *mutationResolver) UpdateListing(ctx context.Context, input *model.Updat
return nil, err
}
}
+
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ mdata["list_id"] = listing.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_LIST_UPDATED,
+ fmt.Sprintf("Updated link listing '%s' (%d)", listing.Slug, listing.ID),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
return listing, nil
}
@@ 3199,6 3468,24 @@ func (r *mutationResolver) UpdateListingLink(ctx context.Context, input *model.U
if err != nil {
return nil, err
}
+
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ mdata["list_id"] = listingLink.ListingID
+ mdata["list_link_id"] = listingLink.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_LIST_LINK_UPDATED,
+ fmt.Sprintf("Updated listing entry '%s' (%d)", listingLink.Title, listingLink.ID),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
return listingLink, nil
}
@@ 3251,6 3538,23 @@ func (r *mutationResolver) DeleteListing(ctx context.Context, id int) (*model.De
if err != nil {
return nil, err
}
+
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ mdata["list_id"] = listing.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_LIST_DELETED,
+ fmt.Sprintf("Deleted link listing '%s' (%d)", listing.Slug, listing.ID),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
deletePayload.Success = true
deletePayload.ObjectID = deletedID
return deletePayload, nil
@@ 3305,6 3609,24 @@ func (r *mutationResolver) DeleteListingLink(ctx context.Context, id int) (*mode
if err != nil {
return nil, err
}
+
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ mdata["list_id"] = listingLink.ListingID
+ mdata["list_link_id"] = listingLink.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_LIST_LINK_DELETED,
+ fmt.Sprintf("Updated listing entry '%s' (%d)", listingLink.Title, listingLink.ID),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
deletePayload.Success = true
deletePayload.ObjectID = deletedID
return deletePayload, nil
@@ 3580,6 3902,23 @@ func (r *mutationResolver) AddQRCode(ctx context.Context, input model.AddQRCodeI
return nil, err
}
}
+
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ mdata["qrcode_id"] = qr.ID
+ mdata["qrcode_type"] = qr.CodeType
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_QRCODE_ADDED,
+ fmt.Sprintf("Added QR code '%s', type: %s (%d)", qr.Title, qr.CodeType, qr.ID),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
return qr, nil
}
@@ 3632,6 3971,24 @@ func (r *mutationResolver) DeleteQRCode(ctx context.Context, id int) (*model.Del
if err != nil {
return nil, err
}
+
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ mdata["qrcode_id"] = qrCode.ID
+ mdata["qrcode_type"] = qrCode.CodeType
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_QRCODE_DELETED,
+ fmt.Sprintf("Deleted QR code '%s', type: %s (%d)", qrCode.Title, qrCode.CodeType, qrCode.ID),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
deletePayload.Success = true
deletePayload.ObjectID = deletedID
return deletePayload, nil
@@ 3677,21 4034,31 @@ func (r *mutationResolver) Follow(ctx context.Context, orgSlug string) (*model.F
return nil, err
}
- if len(follows) > 0 {
- validator.Error("%s", lt.Translate("This user already follows this org")).
- WithField("orgSlug").
- WithCode(valid.ErrValidationCode)
- return nil, nil
- }
+ if len(follows) == 0 {
+ follow := &models.Follower{
+ UserID: int(user.ID),
+ OrgID: org.ID,
+ }
- follow := &models.Follower{
- UserID: int(user.ID),
- OrgID: org.ID,
- }
+ err = follow.Store(ctx)
+ if err != nil {
+ return nil, err
+ }
- err = follow.Store(ctx)
- if err != nil {
- return nil, err
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_ORG_FOLLOW,
+ fmt.Sprintf("Followed organization '%s' (%d)", org.Slug, org.ID),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
}
payload := &model.FollowPayload{
@@ 3754,6 4121,22 @@ func (r *mutationResolver) Unfollow(ctx context.Context, orgSlug string) (*model
if err != nil {
return nil, err
}
+
+ c := server.EchoForContext(ctx)
+ mdata := make(map[string]any)
+ mdata["org_id"] = org.ID
+ err = models.RecordAuditLog(
+ ctx,
+ int(user.ID),
+ c.RealIP(),
+ models.LOG_ORG_UNFOLLOW,
+ fmt.Sprintf("Unfollowed organization '%s' (%d)", org.Slug, org.ID),
+ mdata,
+ )
+ if err != nil {
+ return nil, err
+ }
+
payload := &model.FollowPayload{
Success: true,
Message: lt.Translate("User unfollows %s", orgSlug),