0

I got an upload file functionality in my application and this is working perfectly fine on localhost. However, when will run firebase deploy and the application is deployed I got the following error with lack of permissions.

Edit: I can deploy, there's no problem with the CLI, just on deployment it doesn't work as on localhost.

Tried:

  • This answer: https://stackoverflow.com/a/50298931/11127383
  • Enabling Blaze plan, thus billing too
  • Test on both domains: xxx.web.app and xxx.firebaseapp.com
  • Checked Google Cloud Platform Storage, it has exactly the same uploaded files from localhost as the Firebase Cloud Storage

HTML code

<mat-form-field>
        <!-- Accept only files in the following format: .doc, .docx, .jpg, .jpeg, .pdf, .png, .xls, .xlsx. However, this is easy to bypass, Cloud Storage rules has been set up on the back-end side. -->
        <ngx-mat-file-input
          [accept]="[
            '.doc',
            '.docx',
            '.jpg',
            '.jpeg',
            '.pdf',
            '.png',
            '.xls',
            '.xlsx'
          ]"
          (change)="uploadFile($event)"
          formControlName="fileUploader"
          multiple
          aria-label="Here you can add additional files about your project, which can be helpeful for us."
          placeholder="Additional files"
          title="Additional files"
          type="file"
        >
        </ngx-mat-file-input>
        <mat-icon matSuffix>folder</mat-icon>
        <mat-hint
          >Accepted formats: DOC, DOCX, JPG, JPEG, PDF, PNG, XLS and XLSX,
          maximum files upload size: 20 MB.
        </mat-hint>
        <mat-error
          *ngIf="contactForm.get('fileUploader')!.hasError('maxContentSize')"
        >
          This size is too large,
          <strong
            >maximum acceptable upload size is
            {{
              contactForm.get('fileUploader')?.getError('maxContentSize')
                .maxSize | byteFormat
            }}</strong
          >
          (uploaded size:
          {{
            contactForm.get('fileUploader')?.getError('maxContentSize')
              .actualSize | byteFormat
          }}).
        </mat-error>
      </mat-form-field>

TypeScript (in Angular) code

/**
   * @description Upload additional files to Cloud Firestore and get URL to the files.
   * @param {event} - object of sent files.
   * @returns {void}
   */
  public uploadFile(event: any): void {
    // Iterate through all uploaded files.
    for (let i = 0; i < event.target.files.length; i++) {
      const randomId = Math.random()
        .toString(36)
        .substring(2); // Create random ID, so the same file names can be uploaded to Cloud Firestore.

      const file = event.target.files[i]; // Get each uploaded file.

      // Get file reference.
      const fileRef: AngularFireStorageReference = this.angularFireStorage.ref(
        randomId
      );

      // Create upload task.
      const task: AngularFireUploadTask = this.angularFireStorage.upload(
        randomId,
        file
      );

      // Upload file to Cloud Firestore.
      task
        .snapshotChanges()
        .pipe(
          finalize(() => {
            fileRef.getDownloadURL().subscribe(downloadURL => {
              this.angularFirestore
                .collection('files')
                .add({ downloadURL: downloadURL });
              this.downloadURL.push(downloadURL);
            });
          }),
          catchError((error: any) => {
            return throwError(error);
          })
        )
        .subscribe();
    }
  }

Storage rules

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
        allow read; // Required in order to send this as attachment.
      // Allow write files Firebase Storage, only if:
      // 1) File is no more than 20MB
      // 2) Content type is in one of the following formats: .doc, .docx, .jpg, .jpeg, .pdf, .png, .xls, .xlsx.
      allow write: if request.resource.size <= 20 * 1024 * 1024
                   && (request.resource.contentType.matches('application/msword')
                   || request.resource.contentType.matches('application/vnd.openxmlformats-officedocument.wordprocessingml.document')
                   || request.resource.contentType.matches('image/jpg')
                   || request.resource.contentType.matches('image/jpeg')
                   || request.resource.contentType.matches('application/pdf')
                                     || request.resource.contentType.matches('image/png')
                   || request.resource.contentType.matches('application/vnd.ms-excel')
                   || request.resource.contentType.matches('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'))
    }
  }
}
Daniel Danielecki
  • 8,508
  • 6
  • 68
  • 94
  • Deployment isn't affected by security rules. If your deployment is failing, there's something else wrong. If the error message coming from the CLI isn't helpful, you should reach out to Firebase support for assistance. https://support.google.com/firebase/contact/support – Doug Stevenson Aug 01 '19 at 16:14
  • @DougStevenson I can deploy it, but on the deployment it doesn't works. I think my second sentence was confusing, edited it. – Daniel Danielecki Aug 02 '19 at 08:01

2 Answers2

1

Due to the message you're getting, your issue is related to IAM roles in Firebase.

Here a Quick overview of those.

Check the Error message you are getting and make sure that the instance you're deploying or the service account you're using has the needed roles that let them do the action you want to do.

Kevin Quinzel
  • 1,430
  • 1
  • 13
  • 23
0

Problem solved. The problem was I had GitLab CI pipeline and was injecting the wrong environment variable into the wrong build. If you would have staging and production environment with a similar issue take a look if by mistake you are not injecting staging firebase config into production or vice versa.

Daniel Danielecki
  • 8,508
  • 6
  • 68
  • 94