~edwargix/git.sr.ht

b626d9177f3aeca1814ff21d9386323195717111 — Conrad Hoffmann 2 years ago e02b460
api: expose current user's repository access level

For a given repository, the `access` attribute contains the AccessMode
that applies to the current user.
2 files changed, 44 insertions(+), 0 deletions(-)

M api/graph/schema.graphqls
M api/graph/schema.resolvers.go
M api/graph/schema.graphqls => api/graph/schema.graphqls +4 -0
@@ 132,6 132,10 @@ type Repository {
  """
  readme: String

  "The access that applies to this user for this repository"
  access: AccessMode! @access(scope: ACLS, kind: RO)

  # Only available to the repository owner
  accessControlList(cursor: Cursor): ACLCursor! @access(scope: ACLS, kind: RO)

  ## Plumbing API:

M api/graph/schema.resolvers.go => api/graph/schema.resolvers.go +40 -0
@@ 1064,6 1064,46 @@ func (r *repositoryResolver) Owner(ctx context.Context, obj *model.Repository) (
	return loaders.ForContext(ctx).UsersByID.Load(obj.OwnerID)
}

// Access is the resolver for the access field.
func (r *repositoryResolver) Access(ctx context.Context, obj *model.Repository) (model.AccessMode, error) {
	currentUser := auth.ForContext(ctx)
	if obj.OwnerID == currentUser.UserID {
		return model.AccessModeRw, nil
	}

	mode := model.AccessModeRo
	if err := database.WithTx(ctx, &sql.TxOptions{
		Isolation: 0,
		ReadOnly:  true,
	}, func(tx *sql.Tx) error {
		var rawAccessMode string
		row := tx.QueryRowContext(ctx, `
			SELECT mode
			FROM access
			WHERE
				access.repo_id = $1 AND
				access.user_id = $2;
		`, obj.ID, currentUser.UserID)

		if err := row.Scan(&rawAccessMode); err != nil {
			if err == sql.ErrNoRows {
				return nil
			}
			return err
		}

		mode = model.AccessMode(strings.ToUpper(rawAccessMode))
		if !mode.IsValid() {
			panic(fmt.Errorf("Invalid access mode '%s'", rawAccessMode))
		}
		return nil
	}); err != nil {
		return mode, err
	}

	return mode, nil
}

// AccessControlList is the resolver for the accessControlList field.
func (r *repositoryResolver) AccessControlList(ctx context.Context, obj *model.Repository, cursor *coremodel.Cursor) (*model.ACLCursor, error) {
	if cursor == nil {