func()

in lib/ic/info_release.go [400:487]


func (s *Service) acceptInformationRelease(r *http.Request) (_, _ string, ferr error) {
	stateID := httputils.QueryParam(r, "state")
	if len(stateID) == 0 {
		return "", "", status.Errorf(codes.InvalidArgument, "missing %q parameter", "state")
	}

	rcp, err := toRememberedConsentPreference(r)
	if err != nil {
		return "", "", status.Errorf(codes.InvalidArgument, "accept info release read consent failed: %v", err)
	}

	tx, err := s.store.Tx(true)
	if err != nil {
		return "", "", status.Errorf(codes.Unavailable, "accept info release transaction creation failed: %v", err)
	}
	defer func() {
		err := tx.Finish()
		if ferr == nil && err != nil {
			ferr = status.Errorf(codes.Internal, "accept info release transaction finish failed: %v", err)
		}
	}()

	state := &cpb.LoginState{}
	err = s.store.ReadTx(storage.LoginStateDatatype, storage.DefaultRealm, storage.DefaultUser, stateID, storage.LatestRev, state, tx)
	if err != nil {
		return "", "", status.Errorf(codes.Internal, "accept info release datastore read failed: %v", err)
	}

	// The temporary state for information releasing process can be only used once.
	err = s.store.DeleteTx(storage.LoginStateDatatype, storage.DefaultRealm, storage.DefaultUser, stateID, storage.LatestRev, tx)
	if err != nil {
		return "", "", status.Errorf(codes.Internal, "accept info release datastore delete failed: %v", err)
	}

	challenge := state.ConsentChallenge

	rcp.ClientName = state.ClientName
	// Save RememberedConsent if user select remember it.
	if rcp.RequestMatchType != cspb.RememberedConsentPreference_NONE {
		if err := s.cleanupRememberedConsent(state.Subject, state.Realm, tx); err != nil {
			return challenge, "", err
		}

		rID := uuid.New()
		rcp.RequestedScopes = strings.Split(state.Scope, " ")
		err = s.store.WriteTx(storage.RememberedConsentDatatype, state.Realm, state.Subject, rID, storage.LatestRev, rcp, nil, tx)
		if err != nil {
			return challenge, "", status.Errorf(codes.Internal, "accept info release datastore write remember consent failed: %v", err)
		}
	}

	cfg, err := s.loadConfig(tx, state.Realm)
	if err != nil {
		return challenge, "", status.Errorf(codes.Internal, "accept info release loadConfig() failed: %v", err)
	}

	secrets, err := s.loadSecrets(tx)
	if err != nil {
		return challenge, "", status.Errorf(codes.Internal, "accept info release loadSecrets() failed: %v", err)
	}

	acct, st, err := s.scim.LoadAccount(state.Subject, state.Realm, false, tx)
	if err != nil {
		return challenge, "", status.Errorf(httputils.RPCCode(st), "accept info release LoadAccount() failed: %v", err)
	}

	id, err := s.accountToIdentity(r.Context(), acct, cfg, secrets)
	if err != nil {
		return challenge, "", status.Errorf(codes.Internal, "accept info release accountToIdentity() failed: %v", err)
	}

	now := time.Now().Unix()

	scoped, err := scopedIdentity(id, rcp, state.Scope, s.getIssuerString(), state.Subject, now, id.NotBefore, id.Expiry)
	if err != nil {
		return challenge, "", status.Errorf(codes.Internal, "accept info release scopedIdentity() failed: %v", err)
	}

	if s.useHydra {
		addr, err := s.hydraAcceptConsent(scoped, state)
		if err != nil {
			return challenge, "", status.Errorf(codes.Internal, "accept info release hydraAcceptConsent() failed: %v", err)
		}
		return challenge, addr, nil
	}

	return challenge, "", status.Errorf(codes.Unimplemented, "oidc service not supported")
}