Chris Addis commited on
Commit
bfb1433
·
1 Parent(s): 9e37410
Files changed (2) hide show
  1. .ipynb_checkpoints/app-checkpoint.py +129 -0
  2. app.py +133 -119
.ipynb_checkpoints/app-checkpoint.py ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+
4
+ # --- Configuration ---
5
+ # In your Hugging Face Space settings, add a Secret named `AUTHORIZED_USER_IDS`.
6
+ # The value should be a comma-separated string of the Hugging Face User IDs
7
+ # that you want to grant "full access" to (e.g., "user_id_123,user_id_456").
8
+ # You can find your Hugging Face User ID in your profile URL or settings.
9
+
10
+ # IMPORTANT: This secret should be set in the Hugging Face Space settings, NOT hardcoded here.
11
+ # We retrieve it using os.environ.get() which accesses the Space's environment variables/secrets.
12
+ # Provide a default empty string for local testing where the secret won't exist.
13
+ authorized_users_str = os.environ.get("AUTHORIZED_USER_IDS", "")
14
+ AUTHORIZED_USER_IDS = set(authorized_users_str.split(','))
15
+
16
+ # --- Application Logic ---
17
+
18
+ def get_user_access_level(request: gr.Request):
19
+ """
20
+ Checks the request object to determine if a user is logged in via HF OAuth
21
+ and their access level based on the AUTHORIZED_USER_IDS list.
22
+ Includes a check to prevent AssertionError if request.auth is not available.
23
+ """
24
+ user_info = None
25
+ # Defensive check: Only try to access request.auth if the 'auth' attribute exists
26
+ # and is not None. This prevents the AssertionError if the middleware hasn't run
27
+ # or request.auth isn't populated in this context.
28
+ if hasattr(request, 'auth') and request.auth is not None:
29
+ user_info = request.auth
30
+ # print(f"Accessed request.auth: {user_info}") # Debugging line
31
+ else:
32
+ # print("request.auth not available or is None.") # Debugging line
33
+ pass # Keep print statements minimal in final deployed code
34
+
35
+ if user_info is None:
36
+ # User is not logged in or auth info is not available in the request context
37
+ print("User not logged in or auth info not retrieved via request.auth.")
38
+ return {
39
+ "status_message": "Please sign in with Hugging Face to check your access.",
40
+ "user_identity": "Not Logged In or Auth Info Unavailable",
41
+ "show_login_prompt": gr.update(visible=True),
42
+ "show_limited_content": gr.update(visible=True),
43
+ "show_full_content": gr.update(visible=False)
44
+ }
45
+ else:
46
+ # User info is available (presumably logged in via HF OAuth)
47
+ user_id = user_info.get('sub') # 'sub' is the standard claim for user ID
48
+ username = user_info.get('preferred_username', user_id) # Use username or ID as fallback
49
+
50
+ print(f"Logged in user: Username={username}, ID={user_id}") # Log for debugging
51
+
52
+ # Check if user_id is in the authorized set and is not just an empty string from split(",")
53
+ if user_id in AUTHORIZED_USER_IDS and user_id != "":
54
+ # User is authorized for full access
55
+ print(f"User {user_id} is authorized for full access.")
56
+ return {
57
+ "status_message": f"Welcome, {username}! You have Full Access.",
58
+ "user_identity": f"Logged in as: {username} (ID: {user_id})",
59
+ "show_login_prompt": gr.update(visible=False),
60
+ "show_limited_content": gr.update(visible=False), # Hide limited content for full users
61
+ "show_full_content": gr.update(visible=True)
62
+ }
63
+ else:
64
+ # User is logged in but not authorized for full access
65
+ print(f"User {user_id} is logged in but not authorized.")
66
+ return {
67
+ "status_message": f"Welcome, {username}. You have Limited Access.",
68
+ "user_identity": f"Logged in as: {username} (ID: {user_id})",
69
+ "show_login_prompt": gr.update(visible=False),
70
+ "show_limited_content": gr.update(visible=True),
71
+ "show_full_content": gr.update(visible=False)
72
+ }
73
+
74
+ # --- Gradio Interface ---
75
+
76
+ with gr.Blocks() as demo:
77
+ gr.Markdown("# Hugging Face Spaces Tiered Access Example")
78
+
79
+ # Components to display status and user identity
80
+ status_message = gr.Markdown("Click 'Check My Access Level' after signing in.")
81
+ user_identity_text = gr.Textbox(label="Logged In User Info", interactive=False)
82
+
83
+ # Placeholder for the Login Prompt (visible by default)
84
+ with gr.Column(visible=True) as login_prompt_column:
85
+ gr.Markdown("### Please Sign in with Hugging Face")
86
+ gr.Markdown("*(A 'Sign in with Hugging Face' button will appear automatically above this section when deployed on HF Spaces with OAuth enabled)*")
87
+ # The actual login button is added by Hugging Face Spaces when hf_oauth: true is set in README.md
88
+
89
+ # Content for users with Limited Access (visible by default)
90
+ with gr.Column(visible=True) as limited_content_column:
91
+ gr.Markdown("## Limited Access Content")
92
+ gr.Textbox(value="This is content visible to everyone or users with limited access.", interactive=False)
93
+ gr.Markdown("*(Sign in with Hugging Face and click 'Check My Access Level' to see your status and potentially unlock full features!)*")
94
+ # Add other limited features here
95
+
96
+ # Content for users with Full Access (hidden by default)
97
+ with gr.Column(visible=False) as full_content_column:
98
+ gr.Markdown("## Full Access Content")
99
+ gr.Textbox(value="🥳 Congratulations! You have unlocked the full version! 🥳", interactive=False)
100
+ gr.Markdown("*(This content is only for authorized accounts)*")
101
+ # Add other full features here
102
+
103
+ # This button triggers the check_access_level function.
104
+ # The user should click this *after* potentially signing in via the HF button.
105
+ check_button = gr.Button("Check My Access Level")
106
+
107
+ # Link the button click to the access check function
108
+ # The outputs will update the visibility and text components
109
+ check_button.click(
110
+ fn=get_user_access_level,
111
+ inputs=None, # Request object is implicitly passed by Gradio
112
+ outputs=[
113
+ status_message,
114
+ user_identity_text,
115
+ login_prompt_column,
116
+ limited_content_column,
117
+ full_content_column
118
+ ]
119
+ )
120
+
121
+ # Removed the demo.load() call again, as it seems problematic with request.auth
122
+ # The initial state is controlled by component 'visible' attributes.
123
+
124
+ # --- Launch the App ---
125
+ # For local testing, hf_oauth won't work, request.auth will not be available,
126
+ # but the app should now run without the AssertionError on button click due to the check.
127
+ # It will show the login prompt and limited content.
128
+ # For deployment on HF Spaces, configure README.md and Secrets.
129
+ demo.launch()
app.py CHANGED
@@ -1,129 +1,143 @@
 
1
  import gradio as gr
2
  import os
3
-
4
- # --- Configuration ---
5
- # In your Hugging Face Space settings, add a Secret named `AUTHORIZED_USER_IDS`.
6
- # The value should be a comma-separated string of the Hugging Face User IDs
7
- # that you want to grant "full access" to (e.g., "user_id_123,user_id_456").
8
- # You can find your Hugging Face User ID in your profile URL or settings.
9
 
10
  # IMPORTANT: This secret should be set in the Hugging Face Space settings, NOT hardcoded here.
11
  # We retrieve it using os.environ.get() which accesses the Space's environment variables/secrets.
12
  # Provide a default empty string for local testing where the secret won't exist.
13
- authorized_users_str = os.environ.get("AUTHORIZED_USER_IDS", "")
14
  AUTHORIZED_USER_IDS = set(authorized_users_str.split(','))
15
 
16
- # --- Application Logic ---
17
-
18
- def get_user_access_level(request: gr.Request):
19
- """
20
- Checks the request object to determine if a user is logged in via HF OAuth
21
- and their access level based on the AUTHORIZED_USER_IDS list.
22
- Includes a check to prevent AssertionError if request.auth is not available.
23
- """
24
- user_info = None
25
- # Defensive check: Only try to access request.auth if the 'auth' attribute exists
26
- # and is not None. This prevents the AssertionError if the middleware hasn't run
27
- # or request.auth isn't populated in this context.
28
- if hasattr(request, 'auth') and request.auth is not None:
29
- user_info = request.auth
30
- # print(f"Accessed request.auth: {user_info}") # Debugging line
31
- else:
32
- # print("request.auth not available or is None.") # Debugging line
33
- pass # Keep print statements minimal in final deployed code
34
-
35
- if user_info is None:
36
- # User is not logged in or auth info is not available in the request context
37
- print("User not logged in or auth info not retrieved via request.auth.")
38
- return {
39
- "status_message": "Please sign in with Hugging Face to check your access.",
40
- "user_identity": "Not Logged In or Auth Info Unavailable",
41
- "show_login_prompt": gr.update(visible=True),
42
- "show_limited_content": gr.update(visible=True),
43
- "show_full_content": gr.update(visible=False)
44
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  else:
46
- # User info is available (presumably logged in via HF OAuth)
47
- user_id = user_info.get('sub') # 'sub' is the standard claim for user ID
48
- username = user_info.get('preferred_username', user_id) # Use username or ID as fallback
49
-
50
- print(f"Logged in user: Username={username}, ID={user_id}") # Log for debugging
51
-
52
- # Check if user_id is in the authorized set and is not just an empty string from split(",")
53
- if user_id in AUTHORIZED_USER_IDS and user_id != "":
54
- # User is authorized for full access
55
- print(f"User {user_id} is authorized for full access.")
56
- return {
57
- "status_message": f"Welcome, {username}! You have Full Access.",
58
- "user_identity": f"Logged in as: {username} (ID: {user_id})",
59
- "show_login_prompt": gr.update(visible=False),
60
- "show_limited_content": gr.update(visible=False), # Hide limited content for full users
61
- "show_full_content": gr.update(visible=True)
62
- }
63
- else:
64
- # User is logged in but not authorized for full access
65
- print(f"User {user_id} is logged in but not authorized.")
66
- return {
67
- "status_message": f"Welcome, {username}. You have Limited Access.",
68
- "user_identity": f"Logged in as: {username} (ID: {user_id})",
69
- "show_login_prompt": gr.update(visible=False),
70
- "show_limited_content": gr.update(visible=True),
71
- "show_full_content": gr.update(visible=False)
72
- }
73
-
74
- # --- Gradio Interface ---
75
-
76
- with gr.Blocks() as demo:
77
- gr.Markdown("# Hugging Face Spaces Tiered Access Example")
78
-
79
- # Components to display status and user identity
80
- status_message = gr.Markdown("Click 'Check My Access Level' after signing in.")
81
- user_identity_text = gr.Textbox(label="Logged In User Info", interactive=False)
82
-
83
- # Placeholder for the Login Prompt (visible by default)
84
- with gr.Column(visible=True) as login_prompt_column:
85
- gr.Markdown("### Please Sign in with Hugging Face")
86
- gr.Markdown("*(A 'Sign in with Hugging Face' button will appear automatically above this section when deployed on HF Spaces with OAuth enabled)*")
87
- # The actual login button is added by Hugging Face Spaces when hf_oauth: true is set in README.md
88
-
89
- # Content for users with Limited Access (visible by default)
90
- with gr.Column(visible=True) as limited_content_column:
91
- gr.Markdown("## Limited Access Content")
92
- gr.Textbox(value="This is content visible to everyone or users with limited access.", interactive=False)
93
- gr.Markdown("*(Sign in with Hugging Face and click 'Check My Access Level' to see your status and potentially unlock full features!)*")
94
- # Add other limited features here
95
-
96
- # Content for users with Full Access (hidden by default)
97
- with gr.Column(visible=False) as full_content_column:
98
- gr.Markdown("## Full Access Content")
99
- gr.Textbox(value="🥳 Congratulations! You have unlocked the full version! 🥳", interactive=False)
100
- gr.Markdown("*(This content is only for authorized accounts)*")
101
- # Add other full features here
102
-
103
- # This button triggers the check_access_level function.
104
- # The user should click this *after* potentially signing in via the HF button.
105
- check_button = gr.Button("Check My Access Level")
106
-
107
- # Link the button click to the access check function
108
- # The outputs will update the visibility and text components
109
- check_button.click(
110
- fn=get_user_access_level,
111
- inputs=None, # Request object is implicitly passed by Gradio
112
- outputs=[
113
- status_message,
114
- user_identity_text,
115
- login_prompt_column,
116
- limited_content_column,
117
- full_content_column
118
- ]
119
  )
120
-
121
- # Removed the demo.load() call again, as it seems problematic with request.auth
122
- # The initial state is controlled by component 'visible' attributes.
123
-
124
- # --- Launch the App ---
125
- # For local testing, hf_oauth won't work, request.auth will not be available,
126
- # but the app should now run without the AssertionError on button click due to the check.
127
- # It will show the login prompt and limited content.
128
- # For deployment on HF Spaces, configure README.md and Secrets.
129
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # --- Application Logic ---
2
  import gradio as gr
3
  import os
4
+ from huggingface_hub import HfApi, hf_hub_url
5
+ import json
 
 
 
 
6
 
7
  # IMPORTANT: This secret should be set in the Hugging Face Space settings, NOT hardcoded here.
8
  # We retrieve it using os.environ.get() which accesses the Space's environment variables/secrets.
9
  # Provide a default empty string for local testing where the secret won't exist.
10
+ authorized_users_str = os.environ.get("AUTHORIZED_USER_IDS")
11
  AUTHORIZED_USER_IDS = set(authorized_users_str.split(','))
12
 
13
+ # Function to determine if the current user has full access
14
+ def check_user_access():
15
+ """Check if the current user has full access based on their Hugging Face identity."""
16
+ try:
17
+ # In Hugging Face Spaces, user information is available in environment variables
18
+ # SPACE_ID contains the space name (e.g., username/space-name)
19
+ # USER contains the logged-in username when using the space
20
+ username = os.environ.get("USER")
21
+
22
+ # For local development/testing, you can set a mock username
23
+ if not username and os.environ.get("DEVELOPMENT_MODE"):
24
+ username = os.environ.get("MOCK_USERNAME", "test_user")
25
+
26
+ # If still no username, user is not logged in
27
+ if not username:
28
+ return False, None
29
+
30
+ # Check if user is in the authorized list
31
+ has_full_access = username in AUTHORIZED_USERS
32
+
33
+ return has_full_access, username
34
+ except Exception as e:
35
+ print(f"Error checking user access: {e}")
36
+ return False, None
37
+
38
+ # Example data processing function (limited functionality)
39
+ def process_data_limited(input_text):
40
+ """Process data with limited functionality."""
41
+ return f"Limited processing: {input_text.upper()}"
42
+
43
+ # Example data processing function (full functionality)
44
+ def process_data_full(input_text):
45
+ """Process data with full functionality."""
46
+ word_count = len(input_text.split())
47
+ char_count = len(input_text)
48
+
49
+ analysis = {
50
+ "Original text": input_text,
51
+ "Word count": word_count,
52
+ "Character count": char_count,
53
+ "Uppercase version": input_text.upper(),
54
+ "Lowercase version": input_text.lower(),
55
+ "Reversed text": input_text[::-1]
56
+ }
57
+
58
+ return json.dumps(analysis, indent=2)
59
+
60
+ # Function to handle form submission and apply the appropriate access level
61
+ def handle_submission(input_text):
62
+ has_full_access, username = check_user_access()
63
+
64
+ if has_full_access:
65
+ return process_data_full(input_text), f"Full access granted for {username}", True
66
  else:
67
+ limited_user_display = f"Limited access for {username}" if username else "Limited access (not logged in)"
68
+ return process_data_limited(input_text), limited_user_display, False
69
+
70
+ # Create the Gradio interface
71
+ with gr.Blocks(title="Access Control Demo") as demo:
72
+ gr.Markdown("# Hugging Face Spaces Access Control Demo")
73
+ gr.Markdown("""
74
+ This demo shows how to implement access control in a Gradio app on Hugging Face Spaces.
75
+
76
+ - **Limited access**: Basic functionality only (uppercase conversion)
77
+ - **Full access**: Complete text analysis suite (for authorized users only)
78
+
79
+ To test different access levels, log in with different Hugging Face accounts.
80
+ """)
81
+
82
+ # Get initial access status
83
+ has_full_access, username = check_user_access()
84
+
85
+ # Display current user and access level
86
+ with gr.Row():
87
+ status_display = gr.Textbox(
88
+ value=f"Full access for {username}" if has_full_access else
89
+ f"Limited access for {username}" if username else
90
+ "Limited access (not logged in)",
91
+ label="Current Access Status",
92
+ interactive=False
93
+ )
94
+ access_indicator = gr.Checkbox(
95
+ value=has_full_access,
96
+ label="Full Access",
97
+ interactive=False
98
+ )
99
+
100
+ # Input form
101
+ with gr.Row():
102
+ input_text = gr.Textbox(
103
+ label="Enter text to process",
104
+ placeholder="Type something here...",
105
+ lines=5
106
+ )
107
+
108
+ # Submit button
109
+ submit_btn = gr.Button("Process Text")
110
+
111
+ # Output display
112
+ output_text = gr.Textbox(
113
+ label="Processing Result",
114
+ lines=10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  )
116
+
117
+ # Connect the submit button to the handler function
118
+ submit_btn.click(
119
+ fn=handle_submission,
120
+ inputs=[input_text],
121
+ outputs=[output_text, status_display, access_indicator]
122
+ )
123
+
124
+ # Additional information section
125
+ gr.Markdown("""
126
+ ## How This Works
127
+
128
+ 1. When a user accesses this Gradio app on Hugging Face Spaces, their login identity is available
129
+ 2. The app checks if the username is in the list of authorized users
130
+ 3. Different functionality is provided based on the user's access level
131
+ 4. Full access users get the complete set of features
132
+ 5. Limited access users (or users who aren't logged in) get basic functionality only
133
+
134
+ This pattern can be extended to implement more complex access control scenarios.
135
+ """)
136
+
137
+ # Launch the app
138
+ if __name__ == "__main__":
139
+ # For local development, set an environment variable to mock user identities
140
+ if os.environ.get("DEVELOPMENT_MODE"):
141
+ print("Running in development mode with mock username")
142
+
143
+ demo.launch()