11import { zodResolver } from "@hookform/resolvers/zod" ;
22import { ExternalLink } from "lucide-react" ;
33import Link from "next/link" ;
4- import { useRouter } from "next/router" ;
54import { useEffect , useState } from "react" ;
65import { useForm } from "react-hook-form" ;
76import { toast } from "sonner" ;
@@ -27,18 +26,12 @@ import {
2726} from "@/components/ui/form" ;
2827import { Input } from "@/components/ui/input" ;
2928import { api } from "@/utils/api" ;
30- import { useUrl } from "@/utils/hooks/use-url" ;
3129
3230const Schema = z . object ( {
33- name : z . string ( ) . min ( 1 , {
34- message : "Name is required" ,
35- } ) ,
36- username : z . string ( ) . min ( 1 , {
37- message : "Username is required" ,
38- } ) ,
39- password : z . string ( ) . min ( 1 , {
40- message : "App Password is required" ,
41- } ) ,
31+ name : z . string ( ) . min ( 1 , { message : "Name is required" } ) ,
32+ username : z . string ( ) . min ( 1 , { message : "Username is required" } ) ,
33+ email : z . string ( ) . email ( ) . optional ( ) ,
34+ apiToken : z . string ( ) . min ( 1 , { message : "API Token is required" } ) ,
4235 workspaceName : z . string ( ) . optional ( ) ,
4336} ) ;
4437
@@ -47,14 +40,12 @@ type Schema = z.infer<typeof Schema>;
4740export const AddBitbucketProvider = ( ) => {
4841 const utils = api . useUtils ( ) ;
4942 const [ isOpen , setIsOpen ] = useState ( false ) ;
50- const _url = useUrl ( ) ;
5143 const { mutateAsync, error, isError } = api . bitbucket . create . useMutation ( ) ;
5244 const { data : auth } = api . user . get . useQuery ( ) ;
53- const _router = useRouter ( ) ;
5445 const form = useForm < Schema > ( {
5546 defaultValues : {
5647 username : "" ,
57- password : "" ,
48+ apiToken : "" ,
5849 workspaceName : "" ,
5950 } ,
6051 resolver : zodResolver ( Schema ) ,
@@ -63,18 +54,20 @@ export const AddBitbucketProvider = () => {
6354 useEffect ( ( ) => {
6455 form . reset ( {
6556 username : "" ,
66- password : "" ,
57+ email : "" ,
58+ apiToken : "" ,
6759 workspaceName : "" ,
6860 } ) ;
6961 } , [ form , isOpen ] ) ;
7062
7163 const onSubmit = async ( data : Schema ) => {
7264 await mutateAsync ( {
7365 bitbucketUsername : data . username ,
74- appPassword : data . password ,
66+ apiToken : data . apiToken ,
7567 bitbucketWorkspaceName : data . workspaceName || "" ,
7668 authId : auth ?. id || "" ,
7769 name : data . name || "" ,
70+ bitbucketEmail : data . email || "" ,
7871 } )
7972 . then ( async ( ) => {
8073 await utils . gitProvider . getAll . invalidate ( ) ;
@@ -113,37 +106,46 @@ export const AddBitbucketProvider = () => {
113106 >
114107 < CardContent className = "p-0" >
115108 < div className = "flex flex-col gap-4" >
116- < p className = "text-muted-foreground text-sm" >
117- To integrate your Bitbucket account, you need to create a new
118- App Password in your Bitbucket settings. Follow these steps:
119- </ p >
120- < ol className = "list-decimal list-inside text-sm text-muted-foreground" >
121- < li className = "flex flex-row gap-2 items-center" >
122- Create new App Password{ " " }
123- < Link
124- href = "https://bitbucket.org/account/settings/app-passwords/new"
125- target = "_blank"
126- >
127- < ExternalLink className = "w-fit text-primary size-4" />
128- </ Link >
109+ < AlertBlock type = "warning" >
110+ Bitbucket App Passwords are deprecated for new providers. Use
111+ an API Token instead. Existing providers with App Passwords
112+ will continue to work until 9th June 2026.
113+ </ AlertBlock >
114+
115+ < div className = "mt-1 text-sm" >
116+ Manage tokens in
117+ < Link
118+ href = "https://id.atlassian.com/manage-profile/security/api-tokens"
119+ target = "_blank"
120+ className = "inline-flex items-center gap-1 ml-1"
121+ >
122+ < span > Bitbucket settings</ span >
123+ < ExternalLink className = "w-fit text-primary size-4" />
124+ </ Link >
125+ </ div >
126+ < ul className = "list-disc list-inside ml-4 text-sm text-muted-foreground" >
127+ < li className = "text-muted-foreground text-sm" >
128+ Click on Create API token with scopes
129129 </ li >
130- < li >
131- When creating the App Password, ensure you grant the
132- following permissions:
133- < ul className = "list-disc list-inside ml-4" >
134- < li > Account: Read</ li >
135- < li > Workspace membership: Read</ li >
136- < li > Projects: Read</ li >
137- < li > Repositories: Read</ li >
138- < li > Pull requests: Read</ li >
139- < li > Webhooks: Read and write</ li >
140- </ ul >
130+ < li className = "text-muted-foreground text-sm" >
131+ Select the expiration date (Max 1 year)
141132 </ li >
142- < li >
143- After creating, you'll receive an App Password. Copy it and
144- paste it below along with your Bitbucket username.
133+ < li className = "text-muted-foreground text-sm" >
134+ Select Bitbucket product.
145135 </ li >
146- </ ol >
136+ </ ul >
137+ < p className = "text-muted-foreground text-sm" >
138+ Select the following scopes:
139+ </ p >
140+
141+ < ul className = "list-disc list-inside ml-4 text-sm text-muted-foreground" >
142+ < li > read:repository:bitbucket</ li >
143+ < li > read:pullrequest:bitbucket</ li >
144+ < li > read:webhook:bitbucket</ li >
145+ < li > read:workspace:bitbucket</ li >
146+ < li > write:webhook:bitbucket</ li >
147+ </ ul >
148+
147149 < FormField
148150 control = { form . control }
149151 name = "name"
@@ -152,7 +154,7 @@ export const AddBitbucketProvider = () => {
152154 < FormLabel > Name</ FormLabel >
153155 < FormControl >
154156 < Input
155- placeholder = "Random Name eg( my-personal-account) "
157+ placeholder = "Your Bitbucket Provider, eg: my-personal-account"
156158 { ...field }
157159 />
158160 </ FormControl >
@@ -179,14 +181,27 @@ export const AddBitbucketProvider = () => {
179181
180182 < FormField
181183 control = { form . control }
182- name = "password"
184+ name = "email"
185+ render = { ( { field } ) => (
186+ < FormItem >
187+ < FormLabel > Bitbucket Email</ FormLabel >
188+ < FormControl >
189+ < Input placeholder = "Your Bitbucket email" { ...field } />
190+ </ FormControl >
191+ < FormMessage />
192+ </ FormItem >
193+ ) }
194+ />
195+
196+ < FormField
197+ control = { form . control }
198+ name = "apiToken"
183199 render = { ( { field } ) => (
184200 < FormItem >
185- < FormLabel > App Password </ FormLabel >
201+ < FormLabel > API Token </ FormLabel >
186202 < FormControl >
187203 < Input
188- type = "password"
189- placeholder = "ATBBPDYUC94nR96Nj7Cqpp4pfwKk03573DD2"
204+ placeholder = "Paste your Bitbucket API token"
190205 { ...field }
191206 />
192207 </ FormControl >
@@ -200,7 +215,7 @@ export const AddBitbucketProvider = () => {
200215 name = "workspaceName"
201216 render = { ( { field } ) => (
202217 < FormItem >
203- < FormLabel > Workspace Name (Optional )</ FormLabel >
218+ < FormLabel > Workspace Name (optional )</ FormLabel >
204219 < FormControl >
205220 < Input
206221 placeholder = "For organization accounts"
0 commit comments