Skip to content

Commit ecbab9e

Browse files
Add new endpoint - List Emails (#902)
* Add new endpoint - List Emails * Adding problem filter
1 parent 59bfe4e commit ecbab9e

10 files changed

Lines changed: 92 additions & 1 deletion

File tree

build.sbt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ lazy val github4s = (crossProject(JSPlatform, JVMPlatform))
4242
Test / scalacOptions -= "-Wnonunit-statement",
4343
mimaPreviousArtifacts := Set("com.47deg" %% "github4s" % "0.32.1"),
4444
mimaBinaryIssueFilters ++= Seq(
45-
ProblemFilters.exclude[IncompatibleMethTypeProblem]("github4s.http.HttpClient.this")
45+
ProblemFilters.exclude[IncompatibleMethTypeProblem]("github4s.http.HttpClient.this"),
46+
ProblemFilters.exclude[ReversedMissingMethodProblem]("github4s.algebras.Users.getEmails")
4647
)
4748
)
4849

github4s/shared/src/main/scala/github4s/Decoders.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,4 +424,6 @@ object Decoders {
424424
deriveDecoder[SearchCodeResult]
425425
implicit val decodeSearchCodeResultItem: Decoder[SearchCodeResultItem] =
426426
deriveDecoder[SearchCodeResultItem]
427+
428+
implicit val decoderEmail: Decoder[Email] = deriveDecoder[Email]
427429
}

github4s/shared/src/main/scala/github4s/Encoders.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,4 +293,6 @@ object Encoders {
293293
deriveEncoder[SearchCodeResult]
294294
implicit val encodeSearchCodeResultItem: Encoder[SearchCodeResultItem] =
295295
deriveEncoder[SearchCodeResultItem]
296+
297+
implicit val encoderEmail: Encoder[Email] = deriveEncoder[Email]
296298
}

github4s/shared/src/main/scala/github4s/algebras/Users.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,16 @@ trait Users[F[_]] {
6464
pagination: Option[Pagination] = None,
6565
headers: Map[String, String] = Map()
6666
): F[GHResponse[List[User]]]
67+
68+
/**
69+
* Get information for an authenticated user's associated email addresses
70+
*
71+
* @param pagination Limit and Offset for pagination
72+
* @param headers optional user headers to include in the request
73+
* @return GHResponse[Email] Email details
74+
*/
75+
def getEmails(
76+
pagination: Option[Pagination] = None,
77+
headers: Map[String, String] = Map()
78+
): F[GHResponse[List[Email]]]
6779
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright 2016-2023 47 Degrees Open Source <https://www.47deg.com>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package github4s.domain
18+
19+
final case class Email(
20+
email: String,
21+
primary: Boolean,
22+
verified: Boolean,
23+
visibility: Option[String]
24+
)

github4s/shared/src/main/scala/github4s/interpreters/UsersInterpreter.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,11 @@ class UsersInterpreter[F[_]](implicit client: HttpClient[F]) extends Users[F] {
4545
): F[GHResponse[List[User]]] =
4646
client
4747
.get[List[User]](s"users/$username/following", headers, pagination = pagination)
48+
49+
override def getEmails(
50+
pagination: Option[Pagination],
51+
headers: Map[String, String]
52+
): F[GHResponse[List[Email]]] =
53+
client
54+
.get[List[Email]]("user/emails", headers, pagination = pagination)
4855
}

github4s/shared/src/test/scala/github4s/integration/UsersSpec.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,14 @@ trait UsersSpec extends BaseIntegrationSpec {
106106
response.statusCode shouldBe notFoundStatusCode
107107
}
108108

109+
"Users >> GetEmails" should "return error on Left when no accessToken is provided" taggedAs Integration in {
110+
val response =
111+
clientResource
112+
.use(client => GithubClient[IO](client).users.getEmails(None, headerUserAgent))
113+
.unsafeRunSync()
114+
115+
testIsLeft[GHError.UnauthorizedError, List[Email]](response)
116+
response.statusCode shouldBe unauthorizedStatusCode
117+
}
118+
109119
}

github4s/shared/src/test/scala/github4s/unit/UserSpec.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,15 @@ class UserSpec extends BaseSpec {
7272
users.getFollowing(validUsername, None, headerUserAgent).shouldNotFail
7373
}
7474

75+
"User.getEmails" should "call to httpClient.get with the right parameters" in {
76+
77+
implicit val httpClientMock: HttpClient[IO] = httpClientMockGet[List[Email]](
78+
url = s"user/emails",
79+
response = IO.pure(List(email))
80+
)
81+
82+
val users = new UsersInterpreter[IO]
83+
users.getEmails(None, headerUserAgent).shouldNotFail
84+
}
85+
7586
}

github4s/shared/src/test/scala/github4s/utils/TestData.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,4 +637,7 @@ trait TestData {
637637

638638
val validReviewers: ReviewersRequest =
639639
ReviewersRequest(List(validUsername), List(validSlug))
640+
641+
val email: Email =
642+
Email("developer@47deg.com", primary = true, verified = true, Some("public"))
640643
}

microsite/docs/user.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,23 @@ The `result` on the right is the corresponding [List[User]][user-scala].
112112

113113
See [the API doc](https://developer.github.com/v3/users/followers/#list-users-followed-by-another-use) for full reference.
114114

115+
### List email addresses for the authenticated user
116+
117+
You can get a list of emails associated with the authenticated user using `getEmails`, it takes as argument:
118+
119+
- `pagination`: Limit and Offset for pagination, optional.
120+
121+
```scala mdoc:compile-only
122+
val getEmails = gh.users.getEmails()
123+
getEmails.flatMap(_.result match {
124+
case Left(e) => IO.println(s"Something went wrong: ${e.getMessage}")
125+
case Right(r) => IO.println(r)
126+
})
127+
```
128+
129+
The `result` on the right is the corresponding [List[Email]][email-scala].
130+
131+
See [the API doc](https://developer.github.com/v3/users/emails/#list-email-addresses-for-the-authenticated-user) for full reference.
132+
115133
[user-scala]: https://github.com/47degrees/github4s/blob/main/github4s/shared/src/main/scala/github4s/domain/User.scala
134+
[email-scala]: https://github.com/47degrees/github4s/blob/main/github4s/shared/src/main/scala/github4s/domain/Email.scala

0 commit comments

Comments
 (0)