mirror of
https://github.com/documize/community.git
synced 2025-07-19 05:09:42 +02:00
New user role: view analytics
This commit is contained in:
parent
b65a00dd1c
commit
19a916a4b4
13 changed files with 68 additions and 29 deletions
|
@ -11,6 +11,10 @@ ALTER TABLE rolemember ENGINE = InnoDB;
|
|||
-- content analytics
|
||||
ALTER TABLE useractivity ADD COLUMN `metadata` VARCHAR(1000) NOT NULL DEFAULT '' AFTER `activitytype`;
|
||||
|
||||
-- new role for viewing content analytics
|
||||
ALTER TABLE account ADD COLUMN `analytics` BOOL NOT NULL DEFAULT 0 AFTER `users`;
|
||||
UPDATE account SET analytics=1 WHERE admin=1;
|
||||
|
||||
-- content likes/feedback
|
||||
-- DROP TABLE IF EXISTS `vote`;
|
||||
|
||||
|
@ -31,6 +35,6 @@ ALTER TABLE useractivity ADD COLUMN `metadata` VARCHAR(1000) NOT NULL DEFAULT ''
|
|||
-- DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
|
||||
-- ENGINE = InnoDB;
|
||||
|
||||
-- CREATE INDEX idx_vote_1 ON vaote(orgid,documentid);
|
||||
-- CREATE INDEX idx_vote_1 ON vote(orgid,documentid);
|
||||
|
||||
-- deprecations
|
||||
|
|
|
@ -33,8 +33,8 @@ func (s Scope) Add(ctx domain.RequestContext, account account.Account) (err erro
|
|||
account.Created = time.Now().UTC()
|
||||
account.Revised = time.Now().UTC()
|
||||
|
||||
_, err = ctx.Transaction.Exec("INSERT INTO account (refid, orgid, userid, admin, editor, users, active, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
account.RefID, account.OrgID, account.UserID, account.Admin, account.Editor, account.Users, account.Active, account.Created, account.Revised)
|
||||
_, err = ctx.Transaction.Exec("INSERT INTO account (refid, orgid, userid, admin, editor, users, analytics, active, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
account.RefID, account.OrgID, account.UserID, account.Admin, account.Editor, account.Users, account.Analytics, account.Active, account.Created, account.Revised)
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "unable to execute insert for account")
|
||||
|
@ -46,7 +46,7 @@ func (s Scope) Add(ctx domain.RequestContext, account account.Account) (err erro
|
|||
// GetUserAccount returns the database account record corresponding to the given userID, using the client's current organizaion.
|
||||
func (s Scope) GetUserAccount(ctx domain.RequestContext, userID string) (account account.Account, err error) {
|
||||
err = s.Runtime.Db.Get(&account, `
|
||||
SELECT a.id, a.refid, a.orgid, a.userid, a.editor, a.admin, a.users, a.active, a.created, a.revised,
|
||||
SELECT a.id, a.refid, a.orgid, a.userid, a.editor, a.admin, a.users, a.analytics, a.active, a.created, a.revised,
|
||||
b.company, b.title, b.message, b.domain
|
||||
FROM account a, organization b
|
||||
WHERE b.refid=a.orgid AND a.orgid=? AND a.userid=?`, ctx.OrgID, userID)
|
||||
|
@ -61,8 +61,8 @@ func (s Scope) GetUserAccount(ctx domain.RequestContext, userID string) (account
|
|||
// GetUserAccounts returns a slice of database account records, for all organizations that the userID is a member of, in organization title order.
|
||||
func (s Scope) GetUserAccounts(ctx domain.RequestContext, userID string) (t []account.Account, err error) {
|
||||
err = s.Runtime.Db.Select(&t, `
|
||||
SELECT a.id, a.refid, a.orgid, a.userid, a.editor, a.admin, a.users, a.active, a.created, a.revised,
|
||||
b.company, b.title, b.message, b.domain
|
||||
SELECT a.id, a.refid, a.orgid, a.userid, a.editor, a.admin, a.users, a.analytics, a.active, a.created, a.revised,
|
||||
b.company, b.title, b.message, b.domain
|
||||
FROM account a, organization b
|
||||
WHERE a.userid=? AND a.orgid=b.refid AND a.active=1 ORDER BY b.title`, userID)
|
||||
|
||||
|
@ -76,7 +76,7 @@ func (s Scope) GetUserAccounts(ctx domain.RequestContext, userID string) (t []ac
|
|||
// GetAccountsByOrg returns a slice of database account records, for all users in the client's organization.
|
||||
func (s Scope) GetAccountsByOrg(ctx domain.RequestContext) (t []account.Account, err error) {
|
||||
err = s.Runtime.Db.Select(&t,
|
||||
`SELECT a.id, a.refid, a.orgid, a.userid, a.editor, a.admin, a.users, a.active, a.created, a.revised,
|
||||
`SELECT a.id, a.refid, a.orgid, a.userid, a.editor, a.admin, a.users, a.analytics, a.active, a.created, a.revised,
|
||||
b.company, b.title, b.message, b.domain
|
||||
FROM account a, organization b
|
||||
WHERE a.orgid=b.refid AND a.orgid=? AND a.active=1`, ctx.OrgID)
|
||||
|
@ -109,7 +109,7 @@ func (s Scope) CountOrgAccounts(ctx domain.RequestContext) (c int) {
|
|||
func (s Scope) UpdateAccount(ctx domain.RequestContext, account account.Account) (err error) {
|
||||
account.Revised = time.Now().UTC()
|
||||
|
||||
_, err = ctx.Transaction.NamedExec("UPDATE account SET userid=:userid, admin=:admin, editor=:editor, users=:users, active=:active, revised=:revised WHERE orgid=:orgid AND refid=:refid", &account)
|
||||
_, err = ctx.Transaction.NamedExec("UPDATE account SET userid=:userid, admin=:admin, editor=:editor, users=:users, analytics=:analytics, active=:active, revised=:revised WHERE orgid=:orgid AND refid=:refid", &account)
|
||||
|
||||
if err != sql.ErrNoRows && err != nil {
|
||||
err = errors.Wrap(err, fmt.Sprintf("execute update for account %s", account.RefID))
|
||||
|
|
|
@ -29,6 +29,7 @@ type RequestContext struct {
|
|||
Guest bool
|
||||
Editor bool
|
||||
Global bool
|
||||
Analytics bool
|
||||
UserID string
|
||||
OrgID string
|
||||
OrgName string
|
||||
|
|
|
@ -162,6 +162,7 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
|||
a.Editor = true
|
||||
a.Admin = false
|
||||
a.Active = true
|
||||
a.Analytics = false
|
||||
|
||||
err = h.Store.Account.Add(ctx, a)
|
||||
if err != nil {
|
||||
|
@ -481,6 +482,7 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
|||
a.Admin = u.Admin
|
||||
a.Active = u.Active
|
||||
a.Users = u.ViewUsers
|
||||
a.Analytics = u.Analytics
|
||||
|
||||
err = h.Store.Account.UpdateAccount(ctx, a)
|
||||
if err != nil {
|
||||
|
@ -799,6 +801,7 @@ func (h *Handler) BulkImport(w http.ResponseWriter, r *http.Request) {
|
|||
a.Editor = true
|
||||
a.Admin = false
|
||||
a.Active = true
|
||||
a.Analytics = false
|
||||
|
||||
err = h.Store.Account.Add(ctx, a)
|
||||
if err != nil {
|
||||
|
|
|
@ -114,7 +114,7 @@ func (s Scope) GetActiveUsersForOrganization(ctx domain.RequestContext) (u []use
|
|||
|
||||
err = s.Runtime.Db.Select(&u,
|
||||
`SELECT u.id, u.refid, u.firstname, u.lastname, u.email, u.initials, u.password, u.salt, u.reset, u.lastversion, u.created, u.revised,
|
||||
u.global, a.active, a.editor, a.admin, a.users as viewusers
|
||||
u.global, a.active, a.editor, a.admin, a.users as viewusers, a.analytics
|
||||
FROM user u, account a
|
||||
WHERE u.refid=a.userid AND a.orgid=? AND a.active=1
|
||||
ORDER BY u.firstname,u.lastname`,
|
||||
|
@ -143,7 +143,7 @@ func (s Scope) GetUsersForOrganization(ctx domain.RequestContext, filter string)
|
|||
|
||||
err = s.Runtime.Db.Select(&u,
|
||||
`SELECT u.id, u.refid, u.firstname, u.lastname, u.email, u.initials, u.password, u.salt, u.reset, u.lastversion, u.created, u.revised,
|
||||
u.global, a.active, a.editor, a.admin, a.users as viewusers
|
||||
u.global, a.active, a.editor, a.admin, a.users as viewusers, a.analytics
|
||||
FROM user u, account a
|
||||
WHERE u.refid=a.userid AND a.orgid=? `+likeQuery+
|
||||
`ORDER BY u.firstname, u.lastname LIMIT 100`, ctx.OrgID)
|
||||
|
@ -165,7 +165,7 @@ func (s Scope) GetSpaceUsers(ctx domain.RequestContext, spaceID string) (u []use
|
|||
|
||||
err = s.Runtime.Db.Select(&u, `
|
||||
SELECT u.id, u.refid, u.firstname, u.lastname, u.email, u.initials, u.password, u.salt, u.reset, u.created, u.lastversion, u.revised, u.global,
|
||||
a.active, a.users AS viewusers, a.editor, a.admin
|
||||
a.active, a.users AS viewusers, a.editor, a.admin, a.analytics
|
||||
FROM user u, account a
|
||||
WHERE a.orgid=? AND u.refid = a.userid AND a.active=1 AND u.refid IN (
|
||||
SELECT whoid from permission WHERE orgid=? AND who='user' AND scope='object' AND location='space' AND refid=? UNION ALL
|
||||
|
@ -194,7 +194,7 @@ func (s Scope) GetUsersForSpaces(ctx domain.RequestContext, spaces []string) (u
|
|||
|
||||
query, args, err := sqlx.In(`
|
||||
SELECT u.id, u.refid, u.firstname, u.lastname, u.email, u.initials, u.password, u.salt, u.reset, u.lastversion, u.created, u.revised, u.global,
|
||||
a.active, a.users AS viewusers, a.editor, a.admin
|
||||
a.active, a.users AS viewusers, a.editor, a.admin, a.analytics
|
||||
FROM user u, account a
|
||||
WHERE a.orgid=? AND u.refid = a.userid AND a.active=1 AND u.refid IN (
|
||||
SELECT whoid from permission WHERE orgid=? AND who='user' AND scope='object' AND location='space' AND refid IN(?) UNION ALL
|
||||
|
@ -295,7 +295,7 @@ func (s Scope) MatchUsers(ctx domain.RequestContext, text string, maxMatches int
|
|||
|
||||
err = s.Runtime.Db.Select(&u,
|
||||
`SELECT u.id, u.refid, u.firstname, u.lastname, u.email, u.initials, u.password, u.salt, u.reset, u.lastversion, u.created, u.revised,
|
||||
u.global, a.active, a.editor, a.admin, a.users as viewusers
|
||||
u.global, a.active, a.editor, a.admin, a.users as viewusers, a.analytics
|
||||
FROM user u, account a
|
||||
WHERE a.orgid=? AND u.refid=a.userid AND a.active=1 `+likeQuery+
|
||||
`ORDER BY u.firstname,u.lastname LIMIT `+strconv.Itoa(maxMatches),
|
||||
|
|
|
@ -40,6 +40,7 @@ func AttachUserAccounts(ctx domain.RequestContext, s domain.Store, orgID string,
|
|||
u.Admin = false
|
||||
u.Active = false
|
||||
u.ViewUsers = false
|
||||
u.Analytics = false
|
||||
|
||||
for _, account := range u.Accounts {
|
||||
if account.OrgID == orgID {
|
||||
|
@ -47,6 +48,7 @@ func AttachUserAccounts(ctx domain.RequestContext, s domain.Store, orgID string,
|
|||
u.Editor = account.Editor
|
||||
u.Active = account.Active
|
||||
u.ViewUsers = account.Users
|
||||
u.Analytics = account.Analytics
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ export default Component.extend(AuthProvider, ModalMixin, {
|
|||
init() {
|
||||
this._super(...arguments);
|
||||
this.password = {};
|
||||
this.selectedUsers = [];
|
||||
this.selectedUsers = [];
|
||||
},
|
||||
|
||||
didReceiveAttrs() {
|
||||
|
@ -91,6 +91,13 @@ export default Component.extend(AuthProvider, ModalMixin, {
|
|||
cb(user);
|
||||
},
|
||||
|
||||
toggleAnalytics(id) {
|
||||
let user = this.users.findBy("id", id);
|
||||
user.set('analytics', !user.get('analytics'));
|
||||
let cb = this.get('onSave');
|
||||
cb(user);
|
||||
},
|
||||
|
||||
toggleUsers(id) {
|
||||
let user = this.users.findBy("id", id);
|
||||
user.set('viewUsers', !user.get('viewUsers'));
|
||||
|
@ -208,7 +215,7 @@ export default Component.extend(AuthProvider, ModalMixin, {
|
|||
|
||||
this.get('groupSvc').leave(groupId, userId).then(() => {
|
||||
this.filterUsers();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
onJoinGroup(groupId) {
|
||||
|
@ -222,7 +229,7 @@ export default Component.extend(AuthProvider, ModalMixin, {
|
|||
|
||||
this.get('groupSvc').join(groupId, userId).then(() => {
|
||||
this.filterUsers();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -22,6 +22,7 @@ export default Model.extend({
|
|||
editor: attr('boolean', { defaultValue: false }),
|
||||
admin: attr('boolean', { defaultValue: false }),
|
||||
viewUsers: attr('boolean', { defaultValue: false }),
|
||||
analytics: attr('boolean', { defaultValue: false }),
|
||||
global: attr('boolean', { defaultValue: false }),
|
||||
accounts: attr(),
|
||||
groups: attr(),
|
||||
|
|
|
@ -386,6 +386,8 @@ export default Service.extend({
|
|||
let userHasChangeAwaitingReview = false;
|
||||
let userHasChangeRejected = false;
|
||||
|
||||
if (is.null(source) || is.undefined(source)) source = "";
|
||||
|
||||
return this.get('ajax').request(`fetch/page/${documentId}?source=${source}`, {
|
||||
method: 'GET'
|
||||
}).then((response) => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="view-customize my-5">
|
||||
|
||||
|
||||
<div class="my-2">
|
||||
<span class="font-weight-bold">Spaces</span>
|
||||
<span class="text-muted"> — can add spaces, both personal and shared with others</span>
|
||||
|
@ -12,6 +12,10 @@
|
|||
<span class="font-weight-bold">Admin</span>
|
||||
<span class="text-muted"> — can manage all aspects of Documize, like this screen</span>
|
||||
</div>
|
||||
<div class="my-2">
|
||||
<span class="font-weight-bold">Analytics</span>
|
||||
<span class="text-muted"> — can view analytical reports</span>
|
||||
</div>
|
||||
<div class="mt-2 mb-4">
|
||||
<span class="font-weight-bold">Active</span>
|
||||
<span class="text-muted"> — can login and use Documize</span>
|
||||
|
@ -28,11 +32,12 @@
|
|||
<th class="text-muted">
|
||||
{{#if hasSelectedUsers}}
|
||||
<button id="bulk-delete-users" type="button" class="btn btn-danger" data-toggle="modal" data-target="#admin-user-delete-modal" data-backdrop="static">Delete selected users</button>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</th>
|
||||
<th class="no-width">Spaces</th>
|
||||
<th class="no-width">Visible</th>
|
||||
<th class="no-width">Admin</th>
|
||||
<th class="no-width">Analytics</th>
|
||||
<th class="no-width">Active</th>
|
||||
<th class="no-width">
|
||||
</th>
|
||||
|
@ -87,6 +92,13 @@
|
|||
<i class="material-icons checkbox" {{action 'toggleAdmin' user.id}}>check_box_outline_blank</i>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class="no-width text-center">
|
||||
{{#if user.analytics}}
|
||||
<i class="material-icons checkbox" {{action 'toggleAnalytics' user.id}}>check_box</i>
|
||||
{{else}}
|
||||
<i class="material-icons checkbox" {{action 'toggleAnalytics' user.id}}>check_box_outline_blank</i>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class="no-width text-center">
|
||||
{{#if user.me}}
|
||||
<i class="material-icons color-gray">check_box</i>
|
||||
|
|
|
@ -16,14 +16,15 @@ import "github.com/documize/community/model"
|
|||
// Account links a User to an Organization.
|
||||
type Account struct {
|
||||
model.BaseEntity
|
||||
Admin bool `json:"admin"`
|
||||
Editor bool `json:"editor"`
|
||||
Users bool `json:"viewUsers"` // either view all users or just users in your space
|
||||
UserID string `json:"userId"`
|
||||
OrgID string `json:"orgId"`
|
||||
Company string `json:"company"`
|
||||
Title string `json:"title"`
|
||||
Message string `json:"message"`
|
||||
Domain string `json:"domain"`
|
||||
Active bool `json:"active"`
|
||||
Admin bool `json:"admin"`
|
||||
Editor bool `json:"editor"`
|
||||
Users bool `json:"viewUsers"` // either view all users or just users in your space
|
||||
Analytics bool `json:"analytics"` // view content analytics
|
||||
UserID string `json:"userId"`
|
||||
OrgID string `json:"orgId"`
|
||||
Company string `json:"company"`
|
||||
Title string `json:"title"`
|
||||
Message string `json:"message"`
|
||||
Domain string `json:"domain"`
|
||||
Active bool `json:"active"`
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ type User struct {
|
|||
Editor bool `json:"editor"`
|
||||
Admin bool `json:"admin"`
|
||||
ViewUsers bool `json:"viewUsers"`
|
||||
Analytics bool `json:"analytics"`
|
||||
Global bool `json:"global"`
|
||||
Password string `json:"-"`
|
||||
Salt string `json:"-"`
|
||||
|
|
|
@ -141,6 +141,7 @@ func (m *middleware) Authorize(w http.ResponseWriter, r *http.Request, next http
|
|||
rc.Administrator = false
|
||||
rc.Editor = false
|
||||
rc.Global = false
|
||||
rc.Analytics = false
|
||||
rc.AppURL = r.Host
|
||||
rc.Subdomain = organization.GetSubdomainFromHost(r)
|
||||
rc.SSL = r.TLS != nil
|
||||
|
@ -170,6 +171,7 @@ func (m *middleware) Authorize(w http.ResponseWriter, r *http.Request, next http
|
|||
rc.Administrator = u.Admin
|
||||
rc.Editor = u.Editor
|
||||
rc.Global = u.Global
|
||||
rc.Analytics = u.Analytics
|
||||
rc.Fullname = u.Fullname()
|
||||
|
||||
// We send back with every HTTP request/response cycle the latest
|
||||
|
@ -179,12 +181,14 @@ func (m *middleware) Authorize(w http.ResponseWriter, r *http.Request, next http
|
|||
Active bool `json:"active"`
|
||||
Admin bool `json:"admin"`
|
||||
Editor bool `json:"editor"`
|
||||
Analytics bool `json:"analytics"`
|
||||
ViewUsers bool `json:"viewUsers"`
|
||||
}
|
||||
|
||||
state.Active = u.Active
|
||||
state.Admin = u.Admin
|
||||
state.Editor = u.Editor
|
||||
state.Analytics = u.Analytics
|
||||
state.ViewUsers = u.ViewUsers
|
||||
sb, err := json.Marshal(state)
|
||||
|
||||
|
@ -234,6 +238,7 @@ func (m *middleware) preAuthorizeStaticAssets(rt *env.Runtime, r *http.Request)
|
|||
ctx.OrgName = org.Title
|
||||
ctx.Administrator = false
|
||||
ctx.Editor = false
|
||||
ctx.Analytics = false
|
||||
ctx.Global = false
|
||||
ctx.AppURL = r.Host
|
||||
ctx.SSL = r.TLS != nil
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue