{"record":{"id":"d007b1daefdce87e","repo":"antiwork/gumroad","slug":"your-current-role-as-team-membership-role-humani","errorCode":null,"errorMessage":"Your current role as #{team_membership.role.humanize} cannot perform this action.","messagePattern":"Your current role as #(.+?) cannot perform this action\\.","errorType":"http","errorClass":"Pundit::NotAuthorizedError","httpStatus":401,"severity":"warning","filePath":"app/controllers/concerns/pundit_authorization.rb","lineNumber":53,"sourceCode":"    def settings_main_user_not_authorized\n      # This allows keeping the Nav link to settings_main_path, and redirect to the profile page for those roles\n      # that don't have access to it\n      # All roles have at least read-only access to the profile page\n      redirect_to profile_path\n    end\n\n    # It could happen for reasons like:\n    # - a UI element allows the user to access a resource that is not authorized\n    # - the user manually accessed a page for which is not authorized (i.e. /settings/password by non-owner)\n    # These are not usual use cases of the app, so logging it to be notified there are bugs that need fixing.\n    # Also, do not log and do not set a flash alert when the user is switching accounts, as this is a normal use case.\n    #\n    def default_user_not_authorized(exception)\n      Rails.logger.warn(debug_message(exception)) unless params[\"account_switched\"]\n\n      message = build_error_message\n      if request.format.json? || request.format.js?\n        render json: { success: false, error: message }, status: :unauthorized\n      else\n        flash[:alert] = message unless params[\"account_switched\"]\n        redirect_to dashboard_url\n      end\n    end\n\n    def build_error_message\n      # Some policies (like CommentContextPolicy#index?) do not require the user to be authenticated\n      return \"You are not allowed to perform this action.\" if\n        !user_signed_in? ||\n        logged_in_user.role_owner_for?(current_seller)\n\n      team_membership = logged_in_user.find_user_membership_for_seller!(current_seller)\n\n      \"Your current role as #{team_membership.role.humanize} cannot perform this action.\"\n    rescue ActiveRecord::RecordNotFound\n      # This should not happen, but if it does, we want to be notified so we can fix it\n      ErrorNotifier.notify(\"Team: Could not find membership for user #{logged_in_user.id} and seller #{current_seller.id}\")","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/antiwork/gumroad/blob/afeacbd394069a1cbf0c6c50ee8e900925050370/app/controllers/concerns/pundit_authorization.rb#L35-L71","documentation":"The role-specific sibling of error 293: build_error_message found a team membership for the signed-in user on the current seller, so the denial names their role — \"Your current role as Admin/Marketing/Analyst cannot perform this action.\" Delivered by default_user_not_authorized as a 401 JSON body or a flash alert plus dashboard redirect. It means the user is authenticated and on the team, but their role's permissions do not cover this policy query.","triggerScenarios":"A non-owner team member (e.g. Marketing, Analyst) opens an owner-only page such as /settings/password; a role-scoped nav link points at a controller action their policy denies; an API call made with team-member credentials against an owner-only endpoint.","commonSituations":"New teammates exploring settings they cannot access; a role downgraded while cached UI still shows elevated links; frontend rendering actions based on login state rather than membership role.","solutions":["Compare the user's membership role for the seller against the policy's permitted roles — the warn log line includes policy class, user id, and seller id.","If access is genuinely needed, an owner must change the membership's role; there is no self-service escalation.","Developers: gate nav items and buttons on the pundit policy or membership role so the option is never offered to roles that would be denied."],"exampleFix":"<%# before: shown to every team member %>\n<%= link_to \"Team\", settings_team_path %>\n\n<%# after: only roles whose policy allows it see the link %>\n<%= link_to \"Team\", settings_team_path if policy([:settings, :team]).show? %>","handlingStrategy":"validation","validationCode":"<%# Scope settings navigation by the viewer's membership role %>\n<% if policy([:settings, :team]).show? %>\n  <%= link_to \"Team\", settings_team_path %>\n<% end %>","typeGuard":"# Ruby: check the membership role before offering the action\nmembership = logged_in_user.find_user_membership_for_seller(current_seller)\ncan_manage_team = membership&.role.to_s.in?(%w[owner admin])","tryCatchPattern":"# Handled centrally by the concern (401 JSON or flash + dashboard redirect);\n# the message names the user's humanized role so support can explain the denial immediately","preventionTips":["Derive visible navigation from pundit policies or membership role, not from mere login state.","After changing a teammate's role, invalidate cached UI so stale links do not lead them into denials.","Document each role's permitted areas so owners assign roles that match the teammate's tasks."],"tags":["pundit","authorization","rbac","team-membership","roles"],"backgroundTag":"rbac-role-permission-denied","analyzedSha":"afeacbd394069a1cbf0c6c50ee8e900925050370","analyzedAt":"2026-08-21T17:58:52.159Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}