1package oidc
2
3import (
4	"time"
5
6	"github.com/coreos/go-oidc/v3/oidc"
7	"github.com/hashicorp/cap/oidc/internal/strutils"
8)
9
10// Option defines a common functional options type which can be used in a
11// variadic parameter pattern.
12type Option func(interface{})
13
14// ApplyOpts takes a pointer to the options struct as a set of default options
15// and applies the slice of opts as overrides.
16func ApplyOpts(opts interface{}, opt ...Option) {
17	for _, o := range opt {
18		if o == nil { // ignore any nil Options
19			continue
20		}
21		o(opts)
22	}
23}
24
25// WithNow provides an optional func for determining what the current time it
26// is.
27//
28// Valid for: Config, Tk and Request
29func WithNow(now func() time.Time) Option {
30	return func(o interface{}) {
31		if now == nil {
32			return
33		}
34		switch v := o.(type) {
35		case *configOptions:
36			v.withNowFunc = now
37		case *tokenOptions:
38			v.withNowFunc = now
39		case *reqOptions:
40			v.withNowFunc = now
41		}
42	}
43}
44
45// WithScopes provides an optional list of scopes.
46//
47// Valid for: Config and Request
48func WithScopes(scopes ...string) Option {
49	return func(o interface{}) {
50		if len(scopes) == 0 {
51			return
52		}
53		switch v := o.(type) {
54		case *configOptions:
55			// configOptions already has the oidc.ScopeOpenID in its defaults.
56			scopes = strutils.RemoveDuplicatesStable(scopes, false)
57			v.withScopes = append(v.withScopes, scopes...)
58		case *reqOptions:
59			// need to prepend the oidc.ScopeOpenID
60			ts := append([]string{oidc.ScopeOpenID}, scopes...)
61			scopes = strutils.RemoveDuplicatesStable(ts, false)
62			v.withScopes = append(v.withScopes, scopes...)
63		}
64	}
65}
66
67// WithAudiences provides an optional list of audiences.
68//
69//Valid for: Config and Request
70func WithAudiences(auds ...string) Option {
71	return func(o interface{}) {
72		if len(auds) == 0 {
73			return
74		}
75		auds := strutils.RemoveDuplicatesStable(auds, false)
76		switch v := o.(type) {
77		case *configOptions:
78			v.withAudiences = append(v.withAudiences, auds...)
79		case *reqOptions:
80			v.withAudiences = append(v.withAudiences, auds...)
81		case *userInfoOptions:
82			v.withAudiences = append(v.withAudiences, auds...)
83		}
84	}
85}
86